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

MySQL怎么解決RR mysql怎么解決幻讀

Mysql:RR隔離級別下的幻讀

眾所周知,Mysql在InnoDB下有四種隔離級別:

創(chuàng)新互聯(lián)主要從事成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)潮安,10多年網(wǎng)站建設(shè)經(jīng)驗,價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18982081108

未提交讀(Read Uncommitted)

提交后讀(Read Committed)

可重復(fù)讀(Repeatable Read)

串行化(Serializable)

其中可重復(fù)讀(RR)可以避免臟讀( a事務(wù)讀到b事務(wù)回滾前的數(shù)據(jù))以及可不重復(fù)讀( a事務(wù)在b事務(wù)修改提交的前后,兩次分別讀到的數(shù)據(jù)不一致)。但是對于幻讀(a事務(wù)在b事務(wù)insert提交前后,兩次分別讀到的數(shù)據(jù)不一致),卻存在爭議。

下面我們來做一個試驗:

對于下面這張簡單的數(shù)據(jù)表

id? ? ? ? num

1 ????????11

2 ????????22

3 ????????33

我們開啟a、b兩個事務(wù)

a事務(wù)? ? ? ? ? ? ????b事務(wù)

begin? ? ? ? ? ? ????begin

select * from tb? ? ----

----? ? ? ? ? ? ? ? ? ? insert into tb (id,num)values(4,44)

----? ? ? ? ? ? ? ? ? ? commit

select * from tb? ? ----

commit

試驗結(jié)果:a事務(wù)的兩次select查詢到的結(jié)果相同,在后一次查詢中沒有返回新插入id=4的那條記錄。

據(jù)此,很多人判斷說RR隔離級別下“不存在”幻讀。

但果真如此嗎?----

出現(xiàn)上面的試驗結(jié)果,是因為在RR隔離級別事務(wù)下,Mysql會對前一次select的結(jié)果快照。所以第二次select其實是快照讀(這也正是RR隔離級別下能夠避免不可重復(fù)讀的策略)。

如果我們把試驗條件稍作修改,同樣開啟a、b兩個事務(wù):

a事務(wù)? ? ? ? ? ? ????b事務(wù)

begin? ? ? ? ? ? ????begin

select * from tb? ? ----

----? ? ? ? ? ? ? ? ? ? insert into tb (id,num)values(5,55)

----? ? ? ? ? ? ? ? ? ? commit

update tb set num=num+1? ? ----? ? ? ? #此處a事務(wù)做一次修改操作

select * from tb? ? ----

commit

試驗結(jié)果:在a事務(wù)的第二次select中出現(xiàn)了b事務(wù)新插入的id=5的記錄。

由于做了update操作,之前的快照失效了,所以說RR隔離級別下的快照策略并沒能真正避免幻讀。

ps. 假如給第二次的select查詢上鎖(無論是共享鎖還是排它鎖),也會得到同樣的結(jié)果,都會令快照失效。

為什么mysql默認的隔離級別是rr不是rc

原因:

(1)在rc隔離級別下,事務(wù)沒有g(shù)ap lock鎖,因此可以在小于等于5的范圍內(nèi)插入一條新記錄。

(2)binlog為statement記錄的是master上產(chǎn)生的sql語句,按提交順序記錄的,因此binlog中記錄的是先插入數(shù)據(jù),后刪除數(shù)據(jù)。(雖然master上是先刪除數(shù)據(jù)后插入數(shù)據(jù)),邏輯上產(chǎn)生了不一致。

如何解決:

只需要解決上述問題中的一個就能保證數(shù)據(jù)的同步了。

(1)可以使用rr隔離級別;

(2)使用row格式的binlog;

mysql 的鎖以及間隙鎖

mysql 為并發(fā)事務(wù)同時對一條記錄進行讀寫時,提出了兩種解決方案:

1)使用 mvcc 的方法,實現(xiàn)多事務(wù)的并發(fā)讀寫,但是這種讀只是“快照讀”,一般讀的是歷史版本數(shù)據(jù),還有一種是“當前讀”,一般加鎖實現(xiàn)“當前讀”,或者 insert、update、delete 也是當前讀。

2)使用加鎖的方法,鎖分為共享鎖(讀鎖),排他鎖(寫鎖)

快照讀:就是select

當前讀:特殊的讀操作,插入/更新/刪除操作,屬于當前讀,處理的都是當前的數(shù)據(jù),需要加鎖。

mysql 在 RR 級別怎么處理幻讀的呢?一般來說,RR 級別通過 mvcc 機制,保證讀到低于后面事務(wù)的數(shù)據(jù)。但是 select for update 不會觸發(fā) mvcc,它是當前讀。如果后面事務(wù)插入數(shù)據(jù)并提交,那么在 RR 級別就會讀到插入的數(shù)據(jù)。所以,mysql 使用 行鎖 + gap 鎖(簡稱 next-key 鎖)來防止當前讀的時候插入。

Gap Lock在InnoDB的唯一作用就是防止其他事務(wù)的插入操作,以此防止幻讀的發(fā)生。

Innodb自動使用間隙鎖的條件:

MySQL的RR隔離級別與幻讀問題

最近在網(wǎng)上看了不少mysql鎖的文章,不少文章都提到InnoDB的RR隔離級別(Repeatable Read)無法解決幻讀的問題。對此問題作者親自做了一些實驗,將實驗結(jié)論記錄在此。

本次實驗的mysql版本為5.7.22 。

此篇文章的重點在于通過實驗的形式解釋清楚InnoDB的RR隔離級別是否解決了幻讀問題。所以文中將不會對一些相關(guān)的概念進行解釋,默認讀者已經(jīng)具備相關(guān)知識。如果讀者對于以下的知識點不甚清楚,最好自行查閱相關(guān)資料,理解清楚之后再閱讀接下來的實驗內(nèi)容,以免造成困惑。

進行此次實驗需要具備的知識點(包括但不限于):

創(chuàng)建表結(jié)構(gòu):

創(chuàng)建兩條數(shù)據(jù):

最終的表數(shù)據(jù)如下:

打開兩個終端,連上mysql,分別啟動事務(wù)a和事務(wù)b。

在事務(wù)a和事務(wù)b上面分別執(zhí)行如下命令:

查詢出來的結(jié)果如下:

事務(wù)a:

事務(wù)b:

很明顯事務(wù)b沒有查詢到事務(wù)a未提交的新插入數(shù)據(jù)。原因也很簡單,因為 普通的select語句是快照讀,而事務(wù)b啟動時,它的快照數(shù)據(jù)就已經(jīng)被版本鎖定了 。

那么我們在事務(wù)b里面執(zhí)行如下命令來看看執(zhí)行結(jié)果:

執(zhí)行完成之后我們發(fā)現(xiàn)事務(wù)b此時會block住,原因是 事務(wù)a的insert語句排它鎖住了id為3的新插入數(shù)據(jù),而事務(wù)b想請求所有行的共享鎖,肯定是需要等待的。

那么此時事務(wù)b當前讀id為1或2的數(shù)據(jù)(非事務(wù)a新插入數(shù)據(jù))是否可行呢?

結(jié)論是可行的,因為 tmp_table 存在唯一鍵,且事務(wù)a的insert語句只是鎖住了id為3的行。所以其他事務(wù)獲取其他行的共享鎖是可行的 。讀者可以自行測試,這里就不做演示了。

事務(wù)a和事務(wù)b執(zhí)行如下命令:

事務(wù)b打印的結(jié)果:

還是一樣, 因為普通select是快照讀,事務(wù)b還是讀取到的是快照數(shù)據(jù),所以不包含事務(wù)a提交之后的新數(shù)據(jù) 。

讓我們在事務(wù)b下面使用共享鎖查看當前版本數(shù)據(jù):

結(jié)果如下:

可以查詢到事務(wù)a已提交的新數(shù)據(jù),所以此時使用當前讀就產(chǎn)生了幻讀 。

還有另一種情況也會產(chǎn)生幻讀,并且只需要執(zhí)行普通的select語句。下面請看演示。

在事務(wù)b下面執(zhí)行如下兩條語句:

第一條命令使用update更新了事務(wù)a已提交的新數(shù)據(jù),第二條命令通過普通的select語句查看快照數(shù)據(jù)。

打印結(jié)果如下:

可以看到事務(wù)a已提交的新數(shù)據(jù)被事務(wù)b使用update語句更新了,并且通過普通的select語句給查詢出來了,很顯然,出現(xiàn)了幻讀 。

所以說InnoDB的RR隔離級別沒有或者解決了幻讀問題都不太準確。應(yīng)該說它并沒有完全解決幻讀的問題。

如果在同一個事務(wù)里面,只是總是執(zhí)行普通的select快照讀,是不會產(chǎn)生幻讀的。

但是如果在這個事務(wù)里面通過當前讀或者先更新然后快照讀的形式來讀取數(shù)據(jù),就會產(chǎn)生幻讀。

Phantom Rows

Innodb 中 RR 隔離級別能否防止幻讀?

網(wǎng)站題目:MySQL怎么解決RR mysql怎么解決幻讀
轉(zhuǎn)載注明:http://chinadenli.net/article44/ddoddee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站靜態(tài)網(wǎng)站電子商務(wù)搜索引擎優(yōu)化網(wǎng)站排名網(wǎng)頁設(shè)計公司

廣告

聲明:本網(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è)計公司