mysql事務(wù)的隔離級(jí)別

innodb數(shù)據(jù)庫事務(wù)的隔離級(jí)別

讀未提交(Read Uncommitted)

同時(shí)開啟2個(gè)事務(wù),第一個(gè)事務(wù)里做的修改郑气,第二個(gè)事務(wù)立刻就能查詢到該變化例书。該隔離級(jí)別可能產(chǎn)生的最大問題是憾赁,當(dāng)?shù)谝粋€(gè)事務(wù)回滾時(shí)告喊,所以第二個(gè)事務(wù)之前讀取的數(shù)據(jù)變化是沒有發(fā)生的聪富。也就是我們常說的臟讀肝谭。

讀已提交(Read Committed)

這個(gè)隔離級(jí)別是很多其他數(shù)據(jù)庫默認(rèn)的隔離級(jí)別如oracle 纺铭。同時(shí)開啟2個(gè)事務(wù),第一個(gè)事務(wù)里做的修改搏恤,第二個(gè)事務(wù)無法查詢到該變化汗菜,但是如果第一個(gè)事務(wù)被提交,第二個(gè)事務(wù)立刻能獲取到該數(shù)據(jù)挑社。但是由于sql的執(zhí)行和數(shù)據(jù)庫事務(wù)的提交是有時(shí)間間隔的,所以還是可能發(fā)生幻讀的情況巡揍。第一個(gè)事務(wù)將表中所有數(shù)據(jù)的特定字段進(jìn)行修改痛阻,第二個(gè)事務(wù)向表中插入1條新的記錄,第二個(gè)事務(wù)提交腮敌。第一個(gè)事務(wù)提交阱当。在這種情況下第一個(gè)事務(wù)返回執(zhí)行成功俏扩,但是表中的仍然有1條記錄的數(shù)據(jù)未被修改,就好像發(fā)生了幻覺一樣弊添。而且如果在第一個(gè)事務(wù)中先查詢結(jié)果條數(shù)录淡,然后在執(zhí)行更新操作,而在這個(gè)2個(gè)操作之間第二個(gè)事務(wù)提交了1條記錄油坝,就會(huì)發(fā)生更新操作跟事先查詢確定的結(jié)果條數(shù)不一致的情況嫉戚。也想是發(fā)生了幻覺。

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

該隔離級(jí)別是mysql默認(rèn)的事務(wù)隔離級(jí)別澈圈,在該隔離級(jí)別中彬檀。第一個(gè)事務(wù)能查詢到的數(shù)據(jù),是這個(gè)事務(wù)開啟時(shí)數(shù)據(jù)庫的一個(gè)快照狀態(tài)瞬女,所以即使第二個(gè)事務(wù)已經(jīng)進(jìn)行了數(shù)據(jù)提交窍帝,第一個(gè)事務(wù)依然不能發(fā)現(xiàn)該數(shù)據(jù)。就解決一個(gè)事務(wù)中多次查詢結(jié)果條數(shù)不一致的這個(gè)問題诽偷,這個(gè)問題是幻讀的一個(gè)場景坤学。而插入和刪除操作mysql 使用 Next-Key Lock 來解決幻讀問題。

串行化(Serializable)

在該隔離級(jí)別所有操作都是順序執(zhí)行报慕,不存在并發(fā)問題深浮,所以不存在 臟讀和幻讀。

臟讀場景

我使用的工具為DataGrip每個(gè)查詢窗口相當(dāng)于個(gè)一個(gè)連接卖子。設(shè)置事務(wù)的模式手動(dòng)提交略号,事務(wù)的隔離級(jí)別為讀未提交。


image.png

第一個(gè)窗口執(zhí)行語句

#確認(rèn)數(shù)據(jù)信息
select user_id,balance,now() as now from user where user_id =1

結(jié)果信息

1,430000,2022-05-12 03:10:56

第二個(gè)窗口執(zhí)行信息洋闽,注意當(dāng)前狀態(tài)未提交

update user set balance = balance+100 where user_id =1

第一窗口再次執(zhí)行結(jié)果變?yōu)椋?/p>

1,430100,2022-05-12 03:13:20

第二個(gè)窗口回滾事務(wù)玄柠。第一個(gè)窗口再次執(zhí)行結(jié)果變?yōu)?/p>

1,430000,2022-05-12 03:18:53

如果我們在實(shí)際業(yè)務(wù)中,第一個(gè)窗口在查詢到430100后就進(jìn)行也后續(xù)的業(yè)務(wù)處理诫舅,在第二個(gè)窗口信息回滾后羽利,將會(huì)產(chǎn)生業(yè)務(wù)損失。

幻讀場景

幻讀中的不可重復(fù)讀現(xiàn)象

首先我們先將事務(wù)的隔離級(jí)別改為讀以提交
第一個(gè)窗口執(zhí)行

select * from user

返回結(jié)果

1   430000  2022-05-07 01:02:05
2   2000    2022-05-07 01:05:03
3   2000    2022-05-07 01:06:47

第二個(gè)窗口執(zhí)行

insert into user(user_id,balance) values(4,100);
commit;

重新執(zhí)行第一個(gè)窗口語句

1   430000  2022-05-07 01:02:05
2   2000    2022-05-07 01:05:03
3   2000    2022-05-07 01:06:47
4   100 2022-05-12 03:28:01

在這情況下發(fā)現(xiàn)數(shù)據(jù)多了1條刊懈,產(chǎn)生了不可重復(fù)讀現(xiàn)象这弧,其實(shí)也可以定義為幻讀的一種情況。

幻讀中數(shù)據(jù)更新現(xiàn)象

第一個(gè)窗口執(zhí)行語句

update user set create_time = '1999-01-01 00:00:00' where user_id >0

第二個(gè)窗口執(zhí)行語句

insert into user(user_id,balance) values(5,100);
commit;

第一個(gè)窗口執(zhí)行語句

select * from user

第一個(gè)窗口結(jié)果

1   430000  1999-01-01 00:00:00
2   2000    1999-01-01 00:00:00
3   2000    1999-01-01 00:00:00
4   100 1999-01-01 00:00:00
5   100 2022-05-12 03:33:49

我們發(fā)現(xiàn)第五條記錄一個(gè)createtime 沒有被更新的記錄虚汛,這明顯不是我們想要的結(jié)果匾浪,就是幻讀的第二種場景。

可重復(fù)讀隔離級(jí)別幻讀測試

首先將數(shù)據(jù)庫隔離級(jí)別改為可重復(fù)讀
第一個(gè)窗口執(zhí)行語句

update user set create_time = '1999-01-01 00:00:00' where user_id >0

第二個(gè)窗口執(zhí)行語句

insert into user(user_id,balance) values(6,100);
commit;

在這你會(huì)發(fā)現(xiàn)你的語句無法提交成功卷哩;


image.png

因?yàn)閕nnodb 的可重復(fù)讀蛋辈,讀操作不加鎖,但是寫操作是會(huì)進(jìn)行鎖操作的你的執(zhí)行結(jié)果 最終會(huì)得到 Lock wait timeout exceeded; try restarting transaction
所以innodb 可重復(fù)讀 通過 next key lock 來避免了這種幻讀場景。

但是了解了mysql innodb 避免幻讀的實(shí)現(xiàn)方式后冷溶,我們在實(shí)際的過程中也是會(huì)發(fā)生意料之外的事渐白,因?yàn)樗峭ㄟ^寫操作來加鎖的,我們進(jìn)行下面的實(shí)驗(yàn)逞频;
第一個(gè)窗口執(zhí)行語句

select * from user

執(zhí)行結(jié)果

1   430000  1999-01-01 00:00:00
2   2000    1999-01-01 00:00:00
3   2000    1999-01-01 00:00:00
4   100 1999-01-01 00:00:00
5   100 1999-01-01 00:00:00

第二個(gè)窗口執(zhí)行語句

insert into user(user_id,balance) values(6,100);
commit;

第一個(gè)窗口執(zhí)行語句

select * from user

第一個(gè)窗口執(zhí)行結(jié)果

1   430000  1999-01-01 00:00:00
2   2000    1999-01-01 00:00:00
3   2000    1999-01-01 00:00:00
4   100 1999-01-01 00:00:00
5   100 1999-01-01 00:00:00

第一個(gè)窗口執(zhí)行語句

update user set create_time = '1999-01-01 00:00:00' where user_id >0

第一個(gè)窗口執(zhí)行語句

select * from user

第一個(gè)窗口執(zhí)行結(jié)果

1   430000  1999-01-01 00:00:00
2   2000    1999-01-01 00:00:00
3   2000    1999-01-01 00:00:00
4   100 1999-01-01 00:00:00
5   100 1999-01-01 00:00:00
6   100 1999-01-01 00:00:00

我們發(fā)現(xiàn)記錄6 纯衍,并且該記錄的創(chuàng)建時(shí)間已經(jīng)被更新為1999-01-01 00:00:00 這跟我們想想中的可重復(fù)讀和幻讀的解決發(fā)生了沖突。究其原因是因?yàn)槲覀兊诙€(gè)事務(wù)提交了苗胀。而且在第二個(gè)事務(wù)提交之前 我們第一個(gè)事務(wù)并沒有進(jìn)行寫操作襟诸,所以第一個(gè)事務(wù)對于該表自然也就沒有鎖。就會(huì)產(chǎn)生這種詭異的幻讀現(xiàn)象柒巫。那為什么6這個(gè)記錄為什么會(huì)被查出來呢励堡?因?yàn)閕nnodb 的重復(fù)讀使用的mvvc 多版本并發(fā)控制 ,這個(gè)6 是被這個(gè)事務(wù)更新的堡掏,所以他的版本號(hào)就是這個(gè)事務(wù)的版本號(hào)应结,所有就能看到這條記錄,所以并不是破壞了可重復(fù)讀泉唁,只是可重復(fù)讀的實(shí)現(xiàn)方式導(dǎo)致了這個(gè)結(jié)果鹅龄。

ps:如果你在開發(fā)中使用mybatis 你會(huì)發(fā)現(xiàn)其實(shí)無論數(shù)據(jù)庫的事務(wù)隔離級(jí)別是什么,你一個(gè)事務(wù)中多次查詢同一個(gè)語句你會(huì)得到相同的結(jié)果亭畜,因?yàn)閙ybatis默認(rèn)的一級(jí)緩存是基于sqlsession 的 所以只要你語句和參數(shù)沒有變化就會(huì)的到相同的結(jié)果扮休,所以在上述的場景中你將不會(huì)獲得記錄6 ,你的程序可能會(huì)產(chǎn)生意向不到的bug拴鸵。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末玷坠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子劲藐,更是在濱河造成了極大的恐慌八堡,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聘芜,死亡現(xiàn)場離奇詭異兄渺,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)汰现,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門挂谍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瞎饲,你說我怎么就攤上這事口叙。” “怎么了嗅战?”我有些...
    開封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵庐扫,是天一觀的道長。 經(jīng)常有香客問我,道長形庭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任厌漂,我火速辦了婚禮萨醒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘苇倡。我一直安慰自己富纸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開白布旨椒。 她就那樣靜靜地躺著晓褪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪综慎。 梳的紋絲不亂的頭發(fā)上涣仿,一...
    開封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音示惊,去河邊找鬼好港。 笑死,一個(gè)胖子當(dāng)著我的面吹牛米罚,可吹牛的內(nèi)容都是我干的钧汹。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼录择,長吁一口氣:“原來是場噩夢啊……” “哼拔莱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起隘竭,我...
    開封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬榮一對情侶失蹤塘秦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后货裹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嗤形,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年弧圆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赋兵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡搔预,死狀恐怖霹期,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拯田,我是刑警寧澤历造,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響吭产,放射性物質(zhì)發(fā)生泄漏侣监。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一臣淤、第九天 我趴在偏房一處隱蔽的房頂上張望橄霉。 院中可真熱鬧,春花似錦邑蒋、人聲如沸姓蜂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钱慢。三九已至,卻和暖如春卿堂,著一層夾襖步出監(jiān)牢的瞬間束莫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來泰國打工御吞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留麦箍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓陶珠,卻偏偏與公主長得像挟裂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子揍诽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容