欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

mysql怎么避免幻讀 mysql mvcc解決幻讀

關(guān)于MySQL的幻讀問題,看這一篇就夠了

什么是幻讀?

成都創(chuàng)新互聯(lián)公司是專業(yè)的尖草坪網(wǎng)站建設(shè)公司,尖草坪接單;提供成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行尖草坪網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊,希望更多企業(yè)前來合作!

幻讀指的是一個事務(wù)在前后兩次查詢同一個范圍的時候,后一次查詢看到了前一次查詢沒有看到的行。

首先快照讀是不存在幻讀的,只有當(dāng)前讀(實時讀)才存在幻讀的問題。

幻讀有什么問題?

select ...for update語句就是將相應(yīng)的數(shù)據(jù)行鎖住,但是如果存在幻讀,就把for update的語義破壞了。

如何解決幻讀?

產(chǎn)生幻讀的原因是,行鎖只能鎖住行,但是新插入記錄這個動作,要更新的是記錄之間的“間隙”。因此,為了解決幻讀問題,InnoDB只好引入新的鎖,也就是間隙鎖(Gap Lock)。間隙鎖和行鎖合稱 next-key lock , 每個next-key lock是前開后閉區(qū)間 。

總結(jié)

mysql可重復(fù)讀的幻讀解決方案

首先需要明確的就是“幻讀”概念: 隔離級別是可重復(fù)讀,在一個事務(wù)中前后兩次查詢,查到了其他事務(wù)insert進(jìn)來的數(shù)據(jù)。

強(qiáng)調(diào)的是讀取到了其他事務(wù)插入進(jìn)來的數(shù)據(jù)。

下面來論證一下可重復(fù)讀下幻讀的解決方案

先明確一下,for update語法就是當(dāng)前讀,也就是查詢當(dāng)前已經(jīng)提交的數(shù)據(jù),并且是帶悲觀鎖的。沒有for update就是快照讀,也就是根據(jù)readView讀取的undolog中的數(shù)據(jù)。

如果按照以上猜想,那么整個執(zhí)行結(jié)果就違背了 可重復(fù)讀 的隔離級別了。

那么我們再假設(shè)select * from TABLE where d = 5 for update;這條語句鎖定的是所有被掃描到的數(shù)據(jù)。

這是因為T2階段的update會被阻塞住,畢竟所有被掃描到的記錄都被鎖定了。

按照上述推理過程,很顯然,即使鎖定所有掃描到的數(shù)據(jù)行,也依然存在幻讀的情況。違背了 可重復(fù)讀 的隔離級別。

針對這個情況,我們要解決幻讀的問題,那么就要求針對所有被掃描的記錄行以及還不存在的d=5的記錄行都給鎖住。

至此,當(dāng)前查詢結(jié)果完全滿足 可重復(fù)讀 的隔離級別。

通過以上推論,我們可以總結(jié)一下,在可重復(fù)讀的隔離級別下,解決幻讀除了需要鎖定所有掃描到的記錄行外,還需要鎖定行之間的間隙,也就是通過間隙鎖來解決幻讀的問題。

mysql 解決可提交讀、可重復(fù)讀、幻讀

這張圖本人覺得總結(jié)得挺好的,在一般的互聯(lián)網(wǎng)項目中,基本上用的都是Innodb引擎,一般只涉及到的都是行級鎖,但是如果sql語句中不帶索引進(jìn)行操作,可能會導(dǎo)致鎖表,這是不推薦的,性能非常低,可能會導(dǎo)致全表掃描等,行鎖的具體實現(xiàn)算法有以下幾種mysql特有的鎖:

Record Lock(記錄鎖):單個行記錄的鎖,一般是唯一索引或者主鍵上的加鎖

Gap Lock(間隙鎖):鎖定一個區(qū)間,但是不包括自身,開區(qū)間的鎖,RR級別才會有間隙鎖,間隙鎖的唯一目的是防止區(qū)間數(shù)據(jù)的插入,所以間隙鎖與間隙鎖之間是不會相互阻塞的

Next-key Lock(臨鍵鎖):與間隙鎖的區(qū)別是包括自身,是左開右閉區(qū)間,RR級別才會有

加鎖規(guī)則里面,包含了兩個“原則”、兩個“優(yōu)化”和一個“bug”。

原則 1:加鎖的基本單位是 next-key lock,希望你還記得,next-key lock 是前開后閉區(qū)間。

原則 2:查找過程中訪問到的對象才會加鎖。

優(yōu)化 1:索引上的等值查詢,給唯一索引加鎖的時候,next-key lock 退化為行鎖。

優(yōu)化 2:索引上的等值查詢,向右遍歷時且最后一個值不滿足等值條件的時候,next-key lock 退化為間隙鎖。

一個 bug:唯一索引上的范圍查詢會訪問到不滿足條件的第一個值為止。

舉例來說明上述的原則:

建表

插入數(shù)據(jù):

INSERT INTO t ( id , c , d ) VALUES (0, 0, 0);

INSERT INTO t ( id , c , d ) VALUES (5, 5, 10);

INSERT INTO t ( id , c , d ) VALUES (10, 10, 10);

INSERT INTO t ( id , c , d ) VALUES (15, 15, 15);

INSERT INTO t ( id , c , d ) VALUES (20, 20, 20);

INSERT INTO t ( id , c , d ) VALUES (25, 25, 25);

例子1:鎖表

因為d字段上沒有建索引,所以涉及該字段的查詢加鎖會鎖住整個表

因為d字段上面沒有建立索引,所以事務(wù)1執(zhí)行后會導(dǎo)致整個表被鎖,后面所有的操作都會在等待整個表鎖被釋放

例子2:主鍵/唯一索引 記錄鎖

id字段為主鍵,而且事務(wù)1查詢命中了唯一的記錄,默認(rèn)是加Next-key Lock,區(qū)間是(0,5],但是根據(jù)優(yōu)化1,唯一索引/主鍵上的等值查詢,會退化為行鎖,所以只會鎖5這個記錄。

例子3:主鍵/唯一索引上的間隙鎖

由于表 t 中沒有 id=7 的記錄,所以用我們上面提到的加鎖規(guī)則判斷一下的話:根據(jù)原則 1,加鎖單位是 next-key lock,事務(wù)1加鎖范圍就是 (5,10];同時根據(jù)優(yōu)化 2,這是一個等值查詢 (id=7),而 id=10 不滿足查詢條件,next-key lock 退化成間隙鎖,因此最終加鎖的范圍是 (5,10),所以事務(wù)2會阻塞,事務(wù)3執(zhí)行成功。

例子4:普通索引上的間隙鎖

c字段是普通索引,事務(wù)1執(zhí)行時默認(rèn)是對區(qū)間(0,5]加間隙鎖,根據(jù)優(yōu)化2,非唯一索引/主鍵會繼續(xù)向右遍歷,找到10,所以最終的加鎖為(0,5]的Next-Key鎖+(5,10)的間隙鎖,所以事務(wù)2阻塞,事務(wù)3成功。

例子5:間隙鎖與行鎖

事務(wù)1默認(rèn)的Next-Key鎖區(qū)間是(0,5],根據(jù)優(yōu)化2會向右遍歷,找到不滿足查詢條件的10,退化成間隙鎖,所以事務(wù)1的鎖是(0,5]的Next-Key鎖+(5,10)的間隙鎖,這兩個鎖與行鎖是沖突的,而事務(wù)2申請的Next-Key鎖是和事務(wù)1一樣,但是c=5的行鎖與事務(wù)1沖突,所以產(chǎn)生了阻塞,如果改為update t set d=1000 where c=6;因為此時產(chǎn)生的間隙鎖為(5,10),而間隙鎖與間隙鎖是不沖突的,不會產(chǎn)生阻塞

例子6:lock in share mode鎖覆蓋索引

事務(wù)1存在覆蓋索引的情況,不會去回表,lock in share mode這種情況下只會鎖c字段索引,而事務(wù)2是對主鍵加行鎖,所以兩者不存在沖突。

例子7:主鍵/唯一索引上的范圍查詢

開始執(zhí)行的時候,要找到第一個 id=10 的行,因此本該是 Next-Key Lock(5,10],根據(jù)優(yōu)化 1, 主鍵 id 上的等值條件,退化成行鎖,只加了 id=10 這一行的行鎖。范圍查找就往后繼續(xù)找,找到 id=15 這一行停下來,因此需要加 Next-Key Lock(10,15],所以事務(wù)3是沖突的。

例子8:普通索引上的范圍查詢

開始執(zhí)行時,找到第一個滿足條件的行10,加鎖Next-Key Lock(5,10],因為不是唯一索引,所以不會退化,繼續(xù)向后面找,找到15這一行停下來,因此需要加 Next-Key Lock(10,15],因為是范圍查詢,所以鎖不會退化。

快照讀: 通過MVCC實現(xiàn),該技術(shù)不僅可以保證innodb的可重復(fù)讀,而且可以防止幻讀,但是他讀取的數(shù)據(jù)雖然是一致的,但是數(shù)據(jù)是歷史數(shù)據(jù)。

簡單的select操作(不包括 select … lock in share mode, select … for update)

當(dāng)前讀: 要做到保證數(shù)據(jù)是一致的,同時讀取的數(shù)據(jù)是最新的數(shù)據(jù),innodb提供了next-key lock,即gap鎖與行鎖結(jié)合來實現(xiàn)。

select … lock in share mode

select … for update

insert

update

delete

自己理解:

簡單的select是快照讀,快照讀實現(xiàn)可提交讀,可重復(fù)讀和幻讀是通過MVCC+ReadView實現(xiàn)的,而當(dāng)前讀實現(xiàn)這幾種是通過鎖來實現(xiàn)的,為了說明具體原理,下面介紹下MVCC和ReadView概念,所以簡單的select是通過樂觀鎖實現(xiàn)的,當(dāng)前讀是通過悲觀鎖實現(xiàn)的。

參考文章:

當(dāng)前標(biāo)題:mysql怎么避免幻讀 mysql mvcc解決幻讀
轉(zhuǎn)載來于:http://chinadenli.net/article30/dogscso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷ChatGPT、定制開發(fā)外貿(mào)建站、面包屑導(dǎo)航靜態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)