-
當(dāng)前位置:首頁(yè) > 創(chuàng)意學(xué)院 > 技術(shù) > 專題列表 > 正文
CPUQuota=value
該參數(shù)表示服務(wù)可以獲取的最大 CPU 時(shí)間,value 為百分?jǐn)?shù)形式,高于 100% 表示可使用 1 核以上的 CPU。與 cgroup cpu 控制器 cpu.cfs_quota_us 配置項(xiàng)對(duì)應(yīng)。
MemoryLimit=value
該參數(shù)表示服務(wù)可以使用的最大內(nèi)存量,value 可以使用 K, M, G, T 等后綴表示值的大小。與 cgroup memory 控制器 memory.limit_in_bytes 配置項(xiàng)對(duì)應(yīng)。
讀已提交讀未提交可重復(fù)讀(讀已提交,讀未提交)
大家好!今天讓創(chuàng)意嶺的小編來(lái)大家介紹下關(guān)于讀已提交讀未提交可重復(fù)讀的問(wèn)題,以下是小編對(duì)此問(wèn)題的歸納整理,讓我們一起來(lái)看看吧。
開(kāi)始之前先推薦一個(gè)非常厲害的Ai人工智能工具,一鍵生成原創(chuàng)文章、方案、文案、工作計(jì)劃、工作報(bào)告、論文、代碼、作文、做題和對(duì)話答疑等等
只需要輸入關(guān)鍵詞,就能返回你想要的內(nèi)容,越精準(zhǔn),寫(xiě)出的就越詳細(xì),有微信小程序端、在線網(wǎng)頁(yè)版、PC客戶端
官網(wǎng):https://ai.de1919.com。
創(chuàng)意嶺作為行業(yè)內(nèi)優(yōu)秀的企業(yè),服務(wù)客戶遍布全球各地,如需了解SEO相關(guān)業(yè)務(wù)請(qǐng)撥打電話175-8598-2043,或添加微信:1454722008
本文目錄:
一、mysql 核心內(nèi)容-上
1、SQL語(yǔ)句執(zhí)行流程
MySQL大體上可分為Server層和存儲(chǔ)引擎層兩部分。
Server層:
連接器:TCP握手后服務(wù)器來(lái)驗(yàn)證登陸用戶身份,A用戶創(chuàng)建連接后,管理員對(duì)A用戶權(quán)限修改了也不會(huì)影響到已經(jīng)創(chuàng)建的鏈接權(quán)限,必須重新登陸。
查詢緩存:查詢后的結(jié)果存儲(chǔ)位置,MySQL8.0版本以后已經(jīng)取消,因?yàn)椴樵兙彺媸l繁,得不償失。
分析器:根據(jù)語(yǔ)法規(guī)則,判斷你輸入的這個(gè)SQL語(yǔ)句是否滿足MySQL語(yǔ)法。
優(yōu)化器:多種執(zhí)行策略可實(shí)現(xiàn)目標(biāo),系統(tǒng)自動(dòng)選擇最優(yōu)進(jìn)行執(zhí)行。
執(zhí)行器:判斷是否有權(quán)限,將最終任務(wù)提交到存儲(chǔ)引擎。
存儲(chǔ)引擎層
負(fù)責(zé)數(shù)據(jù)的存儲(chǔ)和提取。其架構(gòu)模式是插件式的,支持InnoDB、MyISAM、Memory等多個(gè)存儲(chǔ)引擎?,F(xiàn)在最常用的存儲(chǔ)引擎是InnoDB,它從MySQL 5.5.5版本開(kāi)始成為了默認(rèn)存儲(chǔ)引擎(經(jīng)常用的也是這個(gè))。
SQL執(zhí)行順序
2、BinLog、RedoLog、UndoLog
BinLog
BinLog是記錄所有數(shù)據(jù)庫(kù)表結(jié)構(gòu)變更(例如create、alter table)以及表數(shù)據(jù)修改(insert、update、delete)的二進(jìn)制日志,主從數(shù)據(jù)庫(kù)同步用到的都是BinLog文件。BinLog日志文件有三種模式。
STATEMENT 模式
內(nèi)容:binlog 記錄可能引起數(shù)據(jù)變更的 sql 語(yǔ)句
優(yōu)勢(shì):該模式下,因?yàn)闆](méi)有記錄實(shí)際的數(shù)據(jù),所以日志量很少 IO 都消耗很低,性能是最優(yōu)的
劣勢(shì):但有些操作并不是確定的,比如 uuid() 函數(shù)會(huì)隨機(jī)產(chǎn)生唯一標(biāo)識(shí),當(dāng)依賴 binlog 回放時(shí),該操作生成的數(shù)據(jù)與原數(shù)據(jù)必然是不同的,此時(shí)可能造成無(wú)法預(yù)料的后果。
ROW 模式
內(nèi)容:在該模式下,binlog 會(huì)記錄每次操作的源數(shù)據(jù)與修改后的目標(biāo)數(shù)據(jù),StreamSets就要求該模式。
優(yōu)勢(shì):可以絕對(duì)精準(zhǔn)的還原,從而保證了數(shù)據(jù)的安全與可靠,并且復(fù)制和數(shù)據(jù)恢復(fù)過(guò)程可以是并發(fā)進(jìn)行的
劣勢(shì):缺點(diǎn)在于 binlog 體積會(huì)非常大,同時(shí),對(duì)于修改記錄多、字段長(zhǎng)度大的操作來(lái)說(shuō),記錄時(shí)性能消耗會(huì)很嚴(yán)重。閱讀的時(shí)候也需要特殊指令來(lái)進(jìn)行讀取數(shù)據(jù)。
MIXED 模式
內(nèi)容:是對(duì)上述STATEMENT 跟 ROW 兩種模式的混合使用。
細(xì)節(jié):對(duì)于絕大部分操作,都是使用 STATEMENT 來(lái)進(jìn)行 binlog 沒(méi)有記錄,只有以下操作使用 ROW 來(lái)實(shí)現(xiàn):表的存儲(chǔ)引擎為 NDB,使用了uuid() 等不確定函數(shù),使用了 insert delay 語(yǔ)句,使用了臨時(shí)表
主從同步流程:
1、主節(jié)點(diǎn)必須啟用二進(jìn)制日志,記錄任何修改了數(shù)據(jù)庫(kù)數(shù)據(jù)的事件。
2、從節(jié)點(diǎn)開(kāi)啟一個(gè)線程(I/O Thread)把自己扮演成 mysql 的客戶端,通過(guò) mysql 協(xié)議,請(qǐng)求主節(jié)點(diǎn)的二進(jìn)制日志文件中的事件 。
3、主節(jié)點(diǎn)啟動(dòng)一個(gè)線程(dump Thread),檢查自己二進(jìn)制日志中的事件,跟對(duì)方請(qǐng)求的位置對(duì)比,如果不帶請(qǐng)求位置參數(shù),則主節(jié)點(diǎn)就會(huì)從第一個(gè)日志文件中的第一個(gè)事件一個(gè)一個(gè)發(fā)送給從節(jié)點(diǎn)。
4、從節(jié)點(diǎn)接收到主節(jié)點(diǎn)發(fā)送過(guò)來(lái)的數(shù)據(jù)把它放置到中繼日志(Relay log)文件中。并記錄該次請(qǐng)求到主節(jié)點(diǎn)的具體哪一個(gè)二進(jìn)制日志文件內(nèi)部的哪一個(gè)位置(主節(jié)點(diǎn)中的二進(jìn)制文件會(huì)有多個(gè))。
5、從節(jié)點(diǎn)啟動(dòng)另外一個(gè)線程(sql Thread ),把 Relay log 中的事件讀取出來(lái),并在本地再執(zhí)行一次。
mysql默認(rèn)的復(fù)制方式是異步的,并且復(fù)制的時(shí)候是有并行復(fù)制能力的。主庫(kù)把日志發(fā)送給從庫(kù)后不管了,這樣會(huì)產(chǎn)生一個(gè)問(wèn)題就是假設(shè)主庫(kù)掛了,從庫(kù)處理失敗了,這時(shí)候從庫(kù)升為主庫(kù)后,日志就丟失了。由此產(chǎn)生兩個(gè)概念。
全同步復(fù)制
主庫(kù)寫(xiě)入binlog后強(qiáng)制同步日志到從庫(kù),所有的從庫(kù)都執(zhí)行完成后才返回給客戶端,但是很顯然這個(gè)方式的話性能會(huì)受到嚴(yán)重影響。
半同步復(fù)制
半同步復(fù)制的邏輯是這樣,從庫(kù)寫(xiě)入日志成功后返回ACK確認(rèn)給主庫(kù),主庫(kù)收到至少一個(gè)從庫(kù)的確認(rèn)就認(rèn)為寫(xiě)操作完成。
還可以延伸到由于主從配置不一樣、主庫(kù)大事務(wù)、從庫(kù)壓力過(guò)大、網(wǎng)絡(luò)震蕩等造成主備延遲,如何避免這個(gè)問(wèn)題?主備切換的時(shí)候用可靠性優(yōu)先原則還是可用性優(yōu)先原則?如何判斷主庫(kù)Crash了?互為主備的情況下如何避免主備循環(huán)復(fù)制?被刪庫(kù)跑路了如何正確恢復(fù)?( o )… 感覺(jué)越來(lái)越扯到DBA的活兒上去了。
RedoLog
可以先通過(guò)下面demo理解:
飯點(diǎn)記賬可以把賬單寫(xiě)在賬本上也可以寫(xiě)在粉板上。有人賒賬或者還賬的話,一般有兩種做法:
1、直接把賬本翻出來(lái),把這次賒的賬加上去或者扣除掉。
2、先在粉板上記下這次的賬,等打烊以后再把賬本翻出來(lái)核算。
生意忙時(shí)選后者,因?yàn)榍罢咛闊┝?。得在密密麻麻的記錄中找到這個(gè)人的賒賬總額信息,找到之后再拿出算盤(pán)計(jì)算,最后再將結(jié)果寫(xiě)回到賬本上。
同樣在MySQL中如果每一次的更新操作都需要寫(xiě)進(jìn)磁盤(pán),然后磁盤(pán)也要找到對(duì)應(yīng)的那條記錄,然后再更新,整個(gè)過(guò)程IO成本、查找成本都很高。而粉板和賬本配合的整個(gè)過(guò)程就是MySQL用到的是Write-Ahead Logging 技術(shù),它的關(guān)鍵點(diǎn)就是先寫(xiě)日志,再寫(xiě)磁盤(pán)。此時(shí)賬本 = BinLog,粉板 = RedoLog。
1、 記錄更新時(shí),InnoDB引擎就會(huì)先把記錄寫(xiě)到RedoLog(粉板)里面,并更新內(nèi)存。同時(shí),InnoDB引擎會(huì)在空閑時(shí)將這個(gè)操作記錄更新到磁盤(pán)里面。
2、 如果更新太多RedoLog處理不了的時(shí)候,需先將RedoLog部分?jǐn)?shù)據(jù)寫(xiě)到磁盤(pán),然后擦除RedoLog部分?jǐn)?shù)據(jù)。RedoLog類似轉(zhuǎn)盤(pán)。
RedoLog有write pos 跟checkpoint
write pos :是當(dāng)前記錄的位置,一邊寫(xiě)一邊后移,寫(xiě)到第3號(hào)文件末尾后就回到0號(hào)文件開(kāi)頭。
check point:是當(dāng)前要擦除的位置,也是往后推移并且循環(huán)的,擦除記錄前要把記錄更新到數(shù)據(jù)文件。
write pos和check point之間的是粉板上還空著的部分,可以用來(lái)記錄新的操作。如果write pos追上checkpoint,表示粉板滿了,這時(shí)候不能再執(zhí)行新的更新,得停下來(lái)先擦掉一些記錄,把checkpoint推進(jìn)一下。
有了redo log,InnoDB就可以保證即使數(shù)據(jù)庫(kù)發(fā)生異常重啟,之前提交的記錄都不會(huì)丟失,這個(gè)能力稱為crash-safe。 redolog兩階段提交:為了讓binlog跟redolog兩份日志之間的邏輯一致。提交流程大致如下:
1 prepare階段 --> 2 寫(xiě)binlog --> 3 commit
當(dāng)在2之前崩潰時(shí),重啟恢復(fù)后發(fā)現(xiàn)沒(méi)有commit,回滾。備份恢復(fù):沒(méi)有binlog 。一致
當(dāng)在3之前崩潰時(shí),重啟恢復(fù)發(fā)現(xiàn)雖沒(méi)有commit,但滿足prepare和binlog完整,所以重啟后會(huì)自動(dòng)commit。備份:有binlog. 一致
binlog跟redolog區(qū)別:
redo log是InnoDB引擎特有的;binlog是MySQL的Server層實(shí)現(xiàn)的,所有引擎都可以使用。
redo log是物理日志,記錄的是在某個(gè)數(shù)據(jù)頁(yè)上做了什么修改;binlog是邏輯日志,記錄的是這個(gè)語(yǔ)句的原始邏輯,比如給ID=2這一行的c字段加1。
redo log是循環(huán)寫(xiě)的,空間固定會(huì)用完;binlog是可以追加寫(xiě)入的。追加寫(xiě)是指binlog文件寫(xiě)到一定大小后會(huì)切換到下一個(gè),并不會(huì)覆蓋以前的日志。
UndoLog
UndoLog 一般是邏輯日志,主要分為兩種:
insert undo log
代表事務(wù)在insert新記錄時(shí)產(chǎn)生的undo log, 只在事務(wù)回滾時(shí)需要,并且在事務(wù)提交后可以被立即丟棄
update undo log
事務(wù)在進(jìn)行update或delete時(shí)產(chǎn)生的undo log; 不僅在事務(wù)回滾時(shí)需要,在快照讀時(shí)也需要;所以不能隨便刪除,只有在快速讀或事務(wù)回滾不涉及該日志時(shí),對(duì)應(yīng)的日志才會(huì)被purge線程統(tǒng)一清除
3、MySQL中的索引
索引的常見(jiàn)模型有哈希表、有序數(shù)組和搜索樹(shù)。
哈希表:一種以KV存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu),只適合等值查詢,不適合范圍查詢。
有序數(shù)組:只適用于靜態(tài)存儲(chǔ)引擎,涉及到插入的時(shí)候比較麻煩??梢詤⒖糐ava中的ArrayList。
搜索樹(shù):按照數(shù)據(jù)結(jié)構(gòu)中的二叉樹(shù)來(lái)存儲(chǔ)數(shù)據(jù),不過(guò)此時(shí)是N叉樹(shù)(B+樹(shù))。廣泛應(yīng)用在存儲(chǔ)引擎層中。
B+樹(shù)比B樹(shù)優(yōu)勢(shì)在于:
B+ 樹(shù)非葉子節(jié)點(diǎn)存儲(chǔ)的只是索引,可以存儲(chǔ)的更多。B+樹(shù)比B樹(shù)更加矮胖,IO次數(shù)更少。
B+ 樹(shù)葉子節(jié)點(diǎn)前后管理,更加方便范圍查詢。同時(shí)結(jié)果都在葉子節(jié)點(diǎn),查詢效率穩(wěn)定。
B+樹(shù)中更有利于對(duì)數(shù)據(jù)掃描,可以避免B樹(shù)的回溯掃描。
索引的優(yōu)點(diǎn):
1、唯一索引可以保證每一行數(shù)據(jù)的唯一性
2、提高查詢速度
3、加速表與表的連接
4、顯著的減少查詢中分組和排序的時(shí)間
5、通過(guò)使用索引,可以在查詢的過(guò)程中,使用優(yōu)化隱藏器,提高系統(tǒng)的性能。
索引的缺點(diǎn):
1、創(chuàng)建跟維護(hù)都需要耗時(shí)
2、創(chuàng)建索引時(shí),需要對(duì)表加鎖,在鎖表的同時(shí),可能會(huì)影響到其他的數(shù)據(jù)操作
3、 索引需要磁盤(pán)的空間進(jìn)行存儲(chǔ),磁盤(pán)占用也很快。
4、當(dāng)對(duì)表中的數(shù)據(jù)進(jìn)行CRUD的時(shí),也會(huì)觸發(fā)索引的維護(hù),而維護(hù)索引需要時(shí)間,可能會(huì)降低數(shù)據(jù)操作性能
索引設(shè)計(jì)的原則不應(yīng)該:
1、索引不是越多越好。索引太多,維護(hù)索引需要時(shí)間跟空間。
2、 頻繁更新的數(shù)據(jù),不宜建索引。
3、數(shù)據(jù)量小的表沒(méi)必要建立索引。
應(yīng)該:
1、重復(fù)率小的列建議生成索引。因?yàn)橹貜?fù)數(shù)據(jù)少,索引樹(shù)查詢更有效率,等價(jià)基數(shù)越大越好。
2、數(shù)據(jù)具有唯一性,建議生成唯一性索引。在數(shù)據(jù)庫(kù)的層面,保證數(shù)據(jù)正確性
3、頻繁group by、order by的列建議生成索引。可以大幅提高分組和排序效率
4、經(jīng)常用于查詢條件的字段建議生成索引。通過(guò)索引查詢,速度更快
索引失效的場(chǎng)景
1、模糊搜索:左模糊或全模糊都會(huì)導(dǎo)致索引失效,比如'%a'和'%a%'。但是右模糊是可以利用索引的,比如'a%' 。
2、隱式類型轉(zhuǎn)換:比如select * from t where name = xxx , name是字符串類型,但是沒(méi)有加引號(hào),所以是由MySQL隱式轉(zhuǎn)換的,所以會(huì)讓索引失效 3、當(dāng)語(yǔ)句中帶有or的時(shí)候:比如select * from t where name=‘sw’ or age=14
4、不符合聯(lián)合索引的最左前綴匹配:(A,B,C)的聯(lián)合索引,你只where了C或B或只有B,C
關(guān)于索引的知識(shí)點(diǎn):
主鍵索引:主鍵索引的葉子節(jié)點(diǎn)存的是整行數(shù)據(jù)信息。在InnoDB里,主鍵索引也被稱為聚簇索引(clustered index)。主鍵自增是無(wú)法保證完全自增的哦,遇到唯一鍵沖突、事務(wù)回滾等都可能導(dǎo)致不連續(xù)。
唯一索引:以唯一列生成的索引,該列不允許有重復(fù)值,但允許有空值(NULL)
普通索引跟唯一索引查詢性能:InnoDB的數(shù)據(jù)是按數(shù)據(jù)頁(yè)為單位來(lái)讀寫(xiě)的,默認(rèn)每頁(yè)16KB,因此這兩種索引查詢數(shù)據(jù)性能差別微乎其微。
change buffer:普通索引用在更新過(guò)程的加速,更新的字段如果在緩存中,如果是普通索引則直接更新即可。如果是唯一索引需要將所有數(shù)據(jù)讀入內(nèi)存來(lái)確保不違背唯一性,所以盡量用普通索引。
非主鍵索引:非主鍵索引的葉子節(jié)點(diǎn)內(nèi)容是主鍵的值。在InnoDB里,非主鍵索引也被稱為二級(jí)索引(secondary index)
回表:先通過(guò)數(shù)據(jù)庫(kù)索引掃描出數(shù)據(jù)所在的行,再通過(guò)行主鍵id取出索引中未提供的數(shù)據(jù),即基于非主鍵索引的查詢需要多掃描一棵索引樹(shù)。
覆蓋索引:如果一個(gè)索引包含(或者說(shuō)覆蓋)所有需要查詢的字段的值,我們就稱之為覆蓋索引。
聯(lián)合索引:相對(duì)單列索引,組合索引是用多個(gè)列組合構(gòu)建的索引,一次性最多聯(lián)合16個(gè)。
最左前綴原則:對(duì)多個(gè)字段同時(shí)建立的組合索引(有順序,ABC,ACB是完全不同的兩種聯(lián)合索引) 以聯(lián)合索引(a,b,c)為例,建立這樣的索引相當(dāng)于建立了索引a、ab、abc三個(gè)索引。另外組合索引實(shí)際還是一個(gè)索引,并非真的創(chuàng)建了多個(gè)索引,只是產(chǎn)生的效果等價(jià)于產(chǎn)生多個(gè)索引。
索引下推:MySQL 5.6引入了索引下推優(yōu)化,可以在索引遍歷過(guò)程中,對(duì)索引中包含的字段先做判斷,過(guò)濾掉不符合條件的記錄,減少回表字?jǐn)?shù)。
索引維護(hù):B+樹(shù)為了維護(hù)索引有序性涉及到頁(yè)分裂跟頁(yè)合并。增刪數(shù)據(jù)時(shí)需考慮頁(yè)空間利用率。
自增主鍵:一般會(huì)建立與業(yè)務(wù)無(wú)關(guān)的自增主鍵,不會(huì)觸發(fā)葉子節(jié)點(diǎn)分裂。
延遲關(guān)聯(lián):通過(guò)使用覆蓋索引查詢返回需要的主鍵,再根據(jù)主鍵關(guān)聯(lián)原表獲得需要的數(shù)據(jù)。
InnoDB存儲(chǔ): * .frm文件是一份定義文件,也就是定義數(shù)據(jù)庫(kù)表是一張?jiān)趺礃拥谋怼?.ibd文件則是該表的索引,數(shù)據(jù)存儲(chǔ)文件,既該表的所有索引樹(shù),所有行記錄數(shù)據(jù)都存儲(chǔ)在該文件中。
MyISAM存儲(chǔ):* .frm文件是一份定義文件,也就是定義數(shù)據(jù)庫(kù)表是一張?jiān)趺礃拥谋怼? .MYD文件是MyISAM存儲(chǔ)引擎表的所有行數(shù)據(jù)的文件。* .MYI文件存放的是MyISAM存儲(chǔ)引擎表的索引相關(guān)數(shù)據(jù)的文件。MyISAM引擎下,表數(shù)據(jù)和表索引數(shù)據(jù)是分開(kāi)存儲(chǔ)的。
MyISAM查詢:在MyISAM下,主鍵索引和輔助鍵索引都屬于非聚簇索引。查詢不管是走主鍵索引,還是非主鍵索引,在葉子結(jié)點(diǎn)得到的都是目的數(shù)據(jù)的地址,還需要通過(guò)該地址,才能在數(shù)據(jù)文件中找到目的數(shù)據(jù)。
PS:InnoDB支持聚簇索引,MyISAM不支持聚簇索引
4、SQL事務(wù)隔離級(jí)別
ACID的四個(gè)特性
原子性(Atomicity):把多個(gè)操作放到一個(gè)事務(wù)中,保證這些操作要么都成功,要么都不成功
一致性(Consistency):理解成一串對(duì)數(shù)據(jù)進(jìn)行操作的程序執(zhí)行下來(lái),不會(huì)對(duì)數(shù)據(jù)產(chǎn)生不好的影響,比如憑空產(chǎn)生,或消失
隔離性(Isolation,又稱獨(dú)立性):隔離性的意思就是多個(gè)事務(wù)之間互相不干擾,即使是并發(fā)事務(wù)的情況下,他們只是兩個(gè)并發(fā)執(zhí)行沒(méi)有交集,互不影響的東西;當(dāng)然實(shí)現(xiàn)中,也不一定需要這么完整隔離性,即不一定需要這么的互不干擾,有時(shí)候還是允許有部分干擾的。所以MySQL可以支持4種事務(wù)隔離性
持久性(Durability):當(dāng)某個(gè)操作操作完畢了,那么結(jié)果就是這樣了,并且這個(gè)操作會(huì)持久化到日志記錄中
PS:ACID中C與CAP定理中C的區(qū)別
ACID的C著重強(qiáng)調(diào)單數(shù)據(jù)庫(kù)事務(wù)操作時(shí),要保證數(shù)據(jù)的完整和正確性,數(shù)據(jù)不會(huì)憑空消失跟增加。CAP 理論中的C指的是對(duì)一個(gè)數(shù)據(jù)多個(gè)備份的讀寫(xiě)一致性
事務(wù)操作可能會(huì)出現(xiàn)的數(shù)據(jù)問(wèn)題
1、臟讀(dirty read):B事務(wù)更改數(shù)據(jù)還未提交,A事務(wù)已經(jīng)看到并且用了。B事務(wù)如果回滾,則A事務(wù)做錯(cuò)了
2、 不可重復(fù)讀(non-repeatable read):不可重復(fù)讀的重點(diǎn)是修改: 同樣的條件, 你讀取過(guò)的數(shù)據(jù), 再次讀取出來(lái)發(fā)現(xiàn)值不一樣了,只需要鎖住滿足條件的記錄
3、 幻讀(phantom read):事務(wù)A先修改了某個(gè)表的所有紀(jì)錄的狀態(tài)字段為已處理,未提交;事務(wù)B也在此時(shí)新增了一條未處理的記錄,并提交了;事務(wù)A隨后查詢記錄,卻發(fā)現(xiàn)有一條記錄是未處理的造成幻讀現(xiàn)象,幻讀僅專指新插入的行?;米x會(huì)造成語(yǔ)義上的問(wèn)題跟數(shù)據(jù)一致性問(wèn)題。
4、 在可重復(fù)讀RR隔離級(jí)別下,普通查詢是快照讀,是不會(huì)看到別的事務(wù)插入的數(shù)據(jù)的。因此,幻讀在當(dāng)前讀下才會(huì)出現(xiàn)。要用間隙鎖解決此問(wèn)題。
在說(shuō)隔離級(jí)別之前,你首先要知道,你隔離得越嚴(yán)實(shí),效率就會(huì)越低。因此很多時(shí)候,我們都要在二者之間尋找一個(gè)平衡點(diǎn)。SQL標(biāo)準(zhǔn)的事務(wù)隔離級(jí)別由低到高如下: 上圖從上到下的模式會(huì)導(dǎo)致系統(tǒng)的并行性能依次降低,安全性依次提高。
讀未提交:別人改數(shù)據(jù)的事務(wù)尚未提交,我在我的事務(wù)中也能讀到。
讀已提交(Oracle默認(rèn)):別人改數(shù)據(jù)的事務(wù)已經(jīng)提交,我在我的事務(wù)中才能讀到。
可重復(fù)讀(MySQL默認(rèn)):別人改數(shù)據(jù)的事務(wù)已經(jīng)提交,我在我的事務(wù)中也不去讀,以此保證重復(fù)讀一致性。
串行:我的事務(wù)尚未提交,別人就別想改數(shù)據(jù)。
標(biāo)準(zhǔn)跟實(shí)現(xiàn):上面都是關(guān)于事務(wù)的標(biāo)準(zhǔn),但是每一種數(shù)據(jù)庫(kù)都有不同的實(shí)現(xiàn),比如MySQL InnDB 默認(rèn)為RR級(jí)別,但是不會(huì)出現(xiàn)幻讀。因?yàn)楫?dāng)事務(wù)A更新了所有記錄的某個(gè)字段,此時(shí)事務(wù)A會(huì)獲得對(duì)這個(gè)表的表鎖,因?yàn)槭聞?wù)A還沒(méi)有提交,所以事務(wù)A獲得的鎖沒(méi)有釋放,此時(shí)事務(wù)B在該表插入新記錄,會(huì)因?yàn)闊o(wú)法獲得該表的鎖,則導(dǎo)致插入操作被阻塞。只有事務(wù)A提交了事務(wù)后,釋放了鎖,事務(wù)B才能進(jìn)行接下去的操作。所以可以說(shuō) MySQL的RR級(jí)別的隔離是已經(jīng)實(shí)現(xiàn)解決了臟讀,不可重復(fù)讀和幻讀的。
5、MySQL中的鎖
無(wú)論是Java的并發(fā)編程還是數(shù)據(jù)庫(kù)的并發(fā)操作都會(huì)涉及到鎖,研發(fā)人員引入了悲觀鎖跟樂(lè)觀鎖這樣一種鎖的設(shè)計(jì)思想。
悲觀鎖:
優(yōu)點(diǎn):適合在寫(xiě)多讀少的并發(fā)環(huán)境中使用,雖然無(wú)法維持非常高的性能,但是在樂(lè)觀鎖無(wú)法提更好的性能前提下,可以做到數(shù)據(jù)的安全性
缺點(diǎn):加鎖會(huì)增加系統(tǒng)開(kāi)銷,雖然能保證數(shù)據(jù)的安全,但數(shù)據(jù)處理吞吐量低,不適合在讀書(shū)寫(xiě)少的場(chǎng)合下使用
樂(lè)觀鎖:
優(yōu)點(diǎn):在讀多寫(xiě)少的并發(fā)場(chǎng)景下,可以避免數(shù)據(jù)庫(kù)加鎖的開(kāi)銷,提高DAO層的響應(yīng)性能,很多情況下ORM工具都有帶有樂(lè)觀鎖的實(shí)現(xiàn),所以這些方法不一定需要我們?nèi)藶榈娜?shí)現(xiàn)。
缺點(diǎn):在寫(xiě)多讀少的并發(fā)場(chǎng)景下,即在寫(xiě)操作競(jìng)爭(zhēng)激烈的情況下,會(huì)導(dǎo)致CAS多次重試,沖突頻率過(guò)高,導(dǎo)致開(kāi)銷比悲觀鎖更高。
實(shí)現(xiàn):數(shù)據(jù)庫(kù)層面的樂(lè)觀鎖其實(shí)跟CAS思想類似, 通數(shù)據(jù)版本號(hào)或者時(shí)間戳也可以實(shí)現(xiàn)。
數(shù)據(jù)庫(kù)并發(fā)場(chǎng)景主要有三種:
讀-讀:不存在任何問(wèn)題,也不需要并發(fā)控制
讀-寫(xiě):有隔離性問(wèn)題,可能遇到臟讀,幻讀,不可重復(fù)讀
寫(xiě)-寫(xiě):可能存更新丟失問(wèn)題,比如第一類更新丟失,第二類更新丟失
兩類更新丟失問(wèn)題:
第一類更新丟失:事務(wù)A的事務(wù)回滾覆蓋了事務(wù)B已提交的結(jié)果 第二類更新丟失:事務(wù)A的提交覆蓋了事務(wù)B已提交的結(jié)果
為了合理貫徹落實(shí)鎖的思想,MySQL中引入了雜七雜八的各種鎖:
鎖分類
MySQL支持三種層級(jí)的鎖定,分別為
表級(jí)鎖定
MySQL中鎖定粒度最大的一種鎖,最常使用的MYISAM與INNODB都支持表級(jí)鎖定。
頁(yè)級(jí)鎖定
是MySQL中鎖定粒度介于行級(jí)鎖和表級(jí)鎖中間的一種鎖,表級(jí)鎖速度快,但沖突多,行級(jí)沖突少,但速度慢。所以取了折衷的頁(yè)級(jí),一次鎖定相鄰的一組記錄。
行級(jí)鎖定
Mysql中鎖定粒度最細(xì)的一種鎖,表示只針對(duì)當(dāng)前操作的行進(jìn)行加鎖。行級(jí)鎖能大大減少數(shù)據(jù)庫(kù)操作的沖突。其加鎖粒度最小,但加鎖的開(kāi)銷也最大行級(jí)鎖不一定比表級(jí)鎖要好:鎖的粒度越細(xì),代價(jià)越高,相比表級(jí)鎖在表的頭部直接加鎖,行級(jí)鎖還要掃描找到對(duì)應(yīng)的行對(duì)其上鎖,這樣的代價(jià)其實(shí)是比較高的,所以表鎖和行鎖各有所長(zhǎng)。
MyISAM中的鎖
雖然MySQL支持表,頁(yè),行三級(jí)鎖定,但MyISAM存儲(chǔ)引擎只支持表鎖。所以MyISAM的加鎖相對(duì)比較開(kāi)銷低,但數(shù)據(jù)操作的并發(fā)性能相對(duì)就不高。但如果寫(xiě)操作都是尾插入,那還是可以支持一定程度的讀寫(xiě)并發(fā)
從MyISAM所支持的鎖中也可以看出,MyISAM是一個(gè)支持讀讀并發(fā),但不支持通用讀寫(xiě)并發(fā),寫(xiě)寫(xiě)并發(fā)的數(shù)據(jù)庫(kù)引擎,所以它更適合用于讀多寫(xiě)少的應(yīng)用場(chǎng)合,一般工程中也用的較少。
InnoDB中的鎖
該模式下支持的鎖實(shí)在是太多了,具體如下:
共享鎖和排他鎖 (Shared and Exclusive Locks)
意向鎖(Intention Locks)
記錄鎖(Record Locks)
間隙鎖(Gap Locks)
臨鍵鎖 (Next-Key Locks)
插入意向鎖(Insert Intention Locks)
主鍵自增鎖 (AUTO-INC Locks)
空間索引斷言鎖(Predicate Locks for Spatial Indexes)
舉個(gè)栗子,比如行鎖里的共享鎖跟排它鎖:lock in share modle 共享讀鎖:
為了確保自己查到的數(shù)據(jù)沒(méi)有被其他的事務(wù)正在修改,也就是說(shuō)確保查到的數(shù)據(jù)是最新的數(shù)據(jù),并且不允許其他人來(lái)修改數(shù)據(jù)。但是自己不一定能夠修改數(shù)據(jù),因?yàn)橛锌赡芷渌氖聞?wù)也對(duì)這些數(shù)據(jù)使用了 in share mode 的方式上了S 鎖。如果不及時(shí)的commit 或者rollback 也可能會(huì)造成大量的事務(wù)等待。
for update排它寫(xiě)鎖:
為了讓自己查到的數(shù)據(jù)確保是最新數(shù)據(jù),并且查到后的數(shù)據(jù)只允許自己來(lái)修改的時(shí)候,需要用到for update。相當(dāng)于一個(gè) update 語(yǔ)句。在業(yè)務(wù)繁忙的情況下,如果事務(wù)沒(méi)有及時(shí)的commit或者rollback 可能會(huì)造成其他事務(wù)長(zhǎng)時(shí)間的等待,從而影響數(shù)據(jù)庫(kù)的并發(fā)使用效率。
Gap Lock間隙鎖:
1、行鎖只能鎖住行,如果在記錄之間的間隙插入數(shù)據(jù)就無(wú)法解決了,因此MySQL引入了間隙鎖(Gap Lock)。間隙鎖是左右開(kāi)區(qū)間。間隙鎖之間不會(huì)沖突。
2、間隙鎖和行鎖合稱NextKeyLock,每個(gè)NextKeyLock是前開(kāi)后閉區(qū)間。
間隙鎖加鎖原則(學(xué)完忘那種):
1、加鎖的基本單位是 NextKeyLock,是前開(kāi)后閉區(qū)間。
2、查找過(guò)程中訪問(wèn)到的對(duì)象才會(huì)加鎖。
3、索引上的等值查詢,給唯一索引加鎖的時(shí)候,NextKeyLock退化為行鎖。
4、索引上的等值查詢,向右遍歷時(shí)且最后一個(gè)值不滿足等值條件的時(shí)候,NextKeyLock退化為間隙鎖。
5、唯一索引上的范圍查詢會(huì)訪問(wèn)到不滿足條件的第一個(gè)值為止。
二、如何處理數(shù)據(jù)庫(kù)并發(fā)問(wèn)題
想要知道如何處理數(shù)據(jù)并發(fā),自然需要先了解數(shù)據(jù)并發(fā)。
什么是數(shù)據(jù)并發(fā)操作呢?
就是同一時(shí)間內(nèi),不同的線程同時(shí)對(duì)一條數(shù)據(jù)進(jìn)行讀寫(xiě)操作。
在互聯(lián)網(wǎng)時(shí)代,一個(gè)系統(tǒng)常常有很多人在使用,因此就可能出現(xiàn)高并發(fā)的現(xiàn)象,也就是不同的用戶同時(shí)對(duì)一條數(shù)據(jù)進(jìn)行操作,如果沒(méi)有有效的處理,自然就會(huì)出現(xiàn)數(shù)據(jù)的異常。而最常見(jiàn)的一種數(shù)據(jù)并發(fā)的場(chǎng)景就是電商中的秒殺,成千上萬(wàn)個(gè)用戶對(duì)在極端的時(shí)間內(nèi),搶購(gòu)一個(gè)商品。針對(duì)這種場(chǎng)景,商品的庫(kù)存就是一個(gè)需要控制的數(shù)據(jù),而多個(gè)用戶對(duì)在同一時(shí)間對(duì)庫(kù)存進(jìn)行重寫(xiě),一個(gè)不小心就可能出現(xiàn)超賣(mài)的情況。
針對(duì)這種情況,我們?nèi)绾斡行У奶幚頂?shù)據(jù)并發(fā)呢?
第一種方案、數(shù)據(jù)庫(kù)鎖
從鎖的基本屬性來(lái)說(shuō),可以分為兩種:一種是共享鎖(S),一種是排它鎖(X)。在MySQL的數(shù)據(jù)庫(kù)中,是有四種隔離級(jí)別的,會(huì)在讀寫(xiě)的時(shí)候,自動(dòng)的使用這兩種鎖,防止數(shù)據(jù)出現(xiàn)混亂。
這四種隔離級(jí)別分別是:
讀未提交(Read Uncommitted)
讀提交(Read Committed)
可重復(fù)讀(Repeated Read)
串行化(Serializable)
當(dāng)然,不同的隔離級(jí)別,效率也是不同的,對(duì)于數(shù)據(jù)的一致性保證也就有不同的結(jié)果。而這些可能出現(xiàn)的又有哪些呢?
臟讀(dirty read)
當(dāng)事務(wù)與事務(wù)之間沒(méi)有任何隔離的時(shí)候,就可能會(huì)出現(xiàn)臟讀。例如:商家想看看所有的訂單有哪些,這時(shí),用戶A提交了一個(gè)訂單,但事務(wù)還沒(méi)提交,商家卻看到了這個(gè)訂單。而這時(shí)就會(huì)出現(xiàn)一種問(wèn)題,當(dāng)商家去操作這個(gè)訂單時(shí),可能用戶A的訂單由于部分問(wèn)題,導(dǎo)致數(shù)據(jù)回滾,事務(wù)沒(méi)有提交,這時(shí)商家的操作就會(huì)失去目標(biāo)。
不可重復(fù)讀(unrepeatable read)
一個(gè)事務(wù)中,兩次讀操作出來(lái)的同一條數(shù)據(jù)值不同,就是不可重復(fù)讀。
例如:我們有一個(gè)事務(wù)A,需要去查詢一下商品庫(kù)存,然后做扣減,這時(shí),事務(wù)B操作了這個(gè)商品,扣減了一部分庫(kù)存,當(dāng)事務(wù)A再次去查詢商品庫(kù)存的時(shí)候,發(fā)現(xiàn)這一次的結(jié)果和上次不同了,這就是不可重復(fù)讀。
幻讀(phantom problem)
一個(gè)事務(wù)中,兩次讀操作出來(lái)的結(jié)果集不同,就是幻讀。
例如:一個(gè)事務(wù)A,去查詢現(xiàn)在已經(jīng)支付的訂單有哪些,得到了一個(gè)結(jié)果集。這時(shí),事務(wù)B新提交了一個(gè)訂單,當(dāng)事務(wù)A再次去查詢時(shí),就會(huì)出現(xiàn),兩次得到的結(jié)果集不同的情況,也就是幻讀了。
那針對(duì)這些結(jié)果,不同的隔離級(jí)別可以干什么呢?
“讀未提(Read Uncommitted)”能預(yù)防啥?啥都預(yù)防不了。
“讀提交(Read Committed)”能預(yù)防啥?使用“快照讀(Snapshot Read)”方式,避免“臟讀”,但是可能出現(xiàn)“不可重復(fù)讀”和“幻讀”。
“可重復(fù)讀(Repeated Red)”能預(yù)防啥?使用“快照讀(Snapshot Read)”方式,鎖住被讀取記錄,避免出現(xiàn)“臟讀”、“不可重復(fù)讀”,但是可能出現(xiàn)“幻讀”。
“串行化(Serializable)”能預(yù)防啥?有效避免“臟讀”、“不可重復(fù)讀”、“幻讀”,不過(guò)運(yùn)行效率奇差。
好了,鎖說(shuō)完了,但是,我們的數(shù)據(jù)庫(kù)鎖,并不能有效的解決并發(fā)的問(wèn)題,只是盡可能保證數(shù)據(jù)的一致性,當(dāng)并發(fā)量特別大時(shí),數(shù)據(jù)庫(kù)還是容易扛不住。那解決數(shù)據(jù)并發(fā)的另一個(gè)手段就是,盡可能的提高處理的速度。
因?yàn)閿?shù)據(jù)的IO要提升難度比較大,那么通過(guò)其他的方式,對(duì)數(shù)據(jù)進(jìn)行處理,減少數(shù)據(jù)庫(kù)的IO,就是提高并發(fā)能力的有效手段了。
最有效的一種方式就是:緩存
想要減少并發(fā)出現(xiàn)的概率,那么讀寫(xiě)的效率越高,讀寫(xiě)的執(zhí)行時(shí)間越短,自然數(shù)據(jù)并發(fā)的可能性就變小了,并發(fā)性能也有提高了。
還是用剛才的秒殺舉例,我們?yōu)榈木褪潜WC庫(kù)存的數(shù)據(jù)不出錯(cuò),賣(mài)出一個(gè)商品,減一個(gè)庫(kù)存,那么,我們就可以將庫(kù)存放在內(nèi)存中進(jìn)行處理。這樣,就能夠保證庫(kù)存有序的及時(shí)扣減,并且不出現(xiàn)問(wèn)題。這樣,我們的數(shù)據(jù)庫(kù)的寫(xiě)操作也變少了,執(zhí)行效率也就大大提高了。
當(dāng)然,常用的分布式緩存方式有:Redis和Memcache,Redis可以持久化到硬盤(pán),而Memcache不行,應(yīng)該怎么選擇,就看具體的使用場(chǎng)景了。
當(dāng)然,緩存畢竟使用的范圍有限,很多的數(shù)據(jù)我們還是必須持久化到硬盤(pán)中,那我們就需要提高數(shù)據(jù)庫(kù)的IO能力,這樣避免一個(gè)線程執(zhí)行時(shí)間太長(zhǎng),造成線程的阻塞。
那么,讀寫(xiě)分離就是另一種有效的方式了
當(dāng)我們的寫(xiě)成為了瓶頸的時(shí)候,讀寫(xiě)分離就是一種可以選擇的方式了。
我們的讀庫(kù)就只需要執(zhí)行讀,寫(xiě)庫(kù)就只需要執(zhí)行寫(xiě),把讀的壓力從主庫(kù)中分離出去,讓主庫(kù)的資源只是用來(lái)保證寫(xiě)的效率,從而提高寫(xiě)操作的性能。
三、mysql默認(rèn)隔離級(jí)別怎么加鎖
修改方法
有兩種方法可以對(duì)配置了 systemd 的程序進(jìn)行資源隔離:1. 命令行修改:通過(guò)執(zhí)行 systemctl set-property 命令實(shí)現(xiàn),形式為 systemctl set-property name parameter=value;修改默認(rèn)即時(shí)生效。2. 手工修改文件:直接編輯程序的 systemd unit file 文件,完成之后需手工執(zhí)行 systemctl daemon-reload 更新配置,并重啟服務(wù) systemctl restart name.service。
systemd unit file 里支持的資源隔離配置項(xiàng),如常見(jiàn)的:
事務(wù)的4種隔離級(jí)別
READ UNCOMMITTED 未提交讀,可以讀取未提交的數(shù)據(jù)。
READ COMMITTED 已提交讀,對(duì)于鎖定讀(select with for update 或者 for share)、update 和 delete 語(yǔ)句,InnoDB 僅鎖定索引記錄,而不鎖定它們之間的間隙,因此允許在鎖定的記錄旁邊自由插入新記錄。
Gap locking 僅用于外鍵約束檢查和重復(fù)鍵檢查。
REPEATABLE READ 可重復(fù)讀,事務(wù)中的一致性讀取讀取的是事務(wù)第一次讀取所建立的快照。
SERIALIZABLE 序列化在了解了 4 種隔離級(jí)別的需求后,在采用鎖控制隔離級(jí)別的基礎(chǔ)上,我們需要了解加鎖的對(duì)象(數(shù)據(jù)本身&間隙),以及了解整個(gè)數(shù)據(jù)范圍的全集組成。
數(shù)據(jù)范圍全集組成
SQL 語(yǔ)句根據(jù)條件判斷不需要掃描的數(shù)據(jù)范圍(不加鎖);
SQL 語(yǔ)句根據(jù)條件掃描到的可能需要加鎖的數(shù)據(jù)范圍;
以單個(gè)數(shù)據(jù)范圍為例,數(shù)據(jù)范圍全集包含:(數(shù)據(jù)范圍不一定是連續(xù)的值,也可能是間隔的值組成)
四、數(shù)據(jù)庫(kù)操作的時(shí)候,什么情況下需要用到事務(wù)?
當(dāng)數(shù)據(jù)庫(kù)需要處理操作量大、復(fù)雜度高的數(shù)據(jù)的時(shí)候需要用到事務(wù)。用事務(wù)是為了保證數(shù)據(jù)庫(kù)的完整性,保證成批的 SQL 語(yǔ)句要么全部執(zhí)行,要么全部不執(zhí)行。
一個(gè)數(shù)據(jù)庫(kù)事務(wù)通常包含了一個(gè)序列的對(duì)數(shù)據(jù)庫(kù)的讀/寫(xiě)操作。它的存在包含有以下兩個(gè)目的:
1、為數(shù)據(jù)庫(kù)操作序列提供了一個(gè)從失敗中恢復(fù)到正常狀態(tài)的方法,同時(shí)提供了數(shù)據(jù)庫(kù)即使在異常狀態(tài)下仍能保持一致性的方法。
2、當(dāng)多個(gè)應(yīng)用程序在并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),可以在這些應(yīng)用程序之間提供一個(gè)隔離方法,以防止彼此的操作互相干擾。
當(dāng)事務(wù)被提交給了數(shù)據(jù)庫(kù)管理系統(tǒng),則數(shù)據(jù)庫(kù)管理系統(tǒng)需要確保該事務(wù)中的所有操作都成功完成且其結(jié)果被永久保存在數(shù)據(jù)庫(kù)中,如果事務(wù)中有的操作沒(méi)有成功完成,則事務(wù)中的所有操作都需要被回滾,回到事務(wù)執(zhí)行前的狀態(tài);同時(shí),該事務(wù)對(duì)數(shù)據(jù)庫(kù)或者其他事務(wù)的執(zhí)行無(wú)影響,所有的事務(wù)都好像在獨(dú)立的運(yùn)行。
擴(kuò)展資料:
數(shù)據(jù)庫(kù)事務(wù)ACID性質(zhì):
1、原子性(Atomicity):事務(wù)作為一個(gè)整體被執(zhí)行,包含在其中的對(duì)數(shù)據(jù)庫(kù)的操作要么全部被執(zhí)行,要么都不執(zhí)行。
2、一致性(Consistency):事務(wù)應(yīng)確保數(shù)據(jù)庫(kù)的狀態(tài)從一個(gè)一致?tīng)顟B(tài)轉(zhuǎn)變?yōu)榱硪粋€(gè)一致?tīng)顟B(tài),一致?tīng)顟B(tài)的含義是數(shù)據(jù)庫(kù)中的數(shù)據(jù)應(yīng)滿足完整性約束。
3、隔離性(Isolation):多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行。
4、持久性(Durability):已被提交的事務(wù)對(duì)數(shù)據(jù)庫(kù)的修改應(yīng)該永久保存在數(shù)據(jù)庫(kù)中。
參考資料來(lái)源:
百度百科-數(shù)據(jù)庫(kù)事務(wù)
百度百科-數(shù)據(jù)庫(kù)
以上就是關(guān)于讀已提交讀未提交可重復(fù)讀相關(guān)問(wèn)題的回答。希望能幫到你,如有更多相關(guān)問(wèn)題,您也可以聯(lián)系我們的客服進(jìn)行咨詢,客服也會(huì)為您講解更多精彩的知識(shí)和內(nèi)容。
推薦閱讀:
讀已提交怎么實(shí)現(xiàn)(讀已提交有什么問(wèn)題)
抖音提現(xiàn)必須本人支付寶嗎(抖音提現(xiàn)必須本人支付寶嗎怎么弄)
浙江小區(qū)景觀設(shè)計(jì)方案(浙江小區(qū)景觀設(shè)計(jì)方案圖)