摘要:眾所周知,在設(shè)定了隔離等級(jí)為及以上時(shí),可以實(shí)現(xiàn)數(shù)據(jù)的一致性讀。換句話來說,就是事務(wù)執(zhí)行的任意時(shí)刻,讀取到的數(shù)據(jù)是同一個(gè)快照,不會(huì)受到其他事務(wù)的更新影響。以前一直以為在事務(wù)內(nèi)讀到的數(shù)據(jù)不會(huì)受其他事務(wù)影響,后來發(fā)現(xiàn)只有普通的語句才是一致性讀。
眾所周知,在設(shè)定了隔離等級(jí)為Repeatable Read及以上時(shí),InnoDB 可以實(shí)現(xiàn)數(shù)據(jù)的一致性讀。換句話來說,就是事務(wù)執(zhí)行的任意時(shí)刻,讀取到的數(shù)據(jù)是同一個(gè)快照,不會(huì)受到其他事務(wù)的更新影響。
以前一直以為在事務(wù)內(nèi)讀到的數(shù)據(jù)不會(huì)受其他事務(wù)影響,后來發(fā)現(xiàn)只有普通的select語句才是一致性讀。如果是update, delete, select for update, select in share mode等語句是當(dāng)前讀,讀的是數(shù)據(jù)庫最新數(shù)據(jù), 下面是兩個(gè)例子。
加鎖讀創(chuàng)建一個(gè)測(cè)試用的表, 然后插入一條測(cè)試用的數(shù)據(jù)
create table test_innodb_read( id int not null primary key, value int ) engine = InnoDB charset=utf8; insert into test_innodb_read values (1, 1);
當(dāng)前autocommit和隔離等級(jí)如下
db83-3306>>select @@autocommit; +--------------+ | @@autocommit | +--------------+ | 1 | +--------------+ 1 row in set (0.00 sec) db83-3306>>select @@transaction_isolation; +-------------------------+ | @@transaction_isolation | +-------------------------+ | REPEATABLE-READ | +-------------------------+ 1 row in set (0.00 sec)
然后開啟兩個(gè) Session,分別執(zhí)行以下操作
時(shí)間點(diǎn) | SessionA | 結(jié)果 | SessionB |
---|---|---|---|
1 |
begin select * from test_innodb_read where id=1 |
1 | |
2 | update test_innodb_read set value = 2 where id=1 | ||
3 | select * from test_innodb_read where id=1 | 1 | |
4 | select * from test_innodb_read where id=1 lock in share mode | 2 |
由于設(shè)置了自動(dòng)提交,所以SessionB的更新語句執(zhí)行完就已經(jīng)提交了,從結(jié)果可以看到普通的Select不受其他事務(wù)影響,所以讀到的數(shù)據(jù)都是同一版本,而在加鎖讀的情況下采取的是讀最新的數(shù)據(jù),所以讀到的數(shù)據(jù)是最新提交的數(shù)據(jù)。
DML 操作在進(jìn)行數(shù)據(jù)變更操作的時(shí)候,也會(huì)拿到最新的數(shù)據(jù),用的還是上面的表,插入一條測(cè)試數(shù)據(jù)
insert into test_innodb_read values (2, 1);
然后開啟兩個(gè) Session,分別執(zhí)行以下操作,
時(shí)間點(diǎn) | SessionA | 結(jié)果 | SessionB |
---|---|---|---|
1 |
begin select * from test_innodb_read where id=2 |
1 | |
2 | update test_innodb_read set value = 2 where id=2 | ||
3 | select * from test_innodb_read where id=2 | 1 | |
4 | update test_innodb_read set value=value+1 where id=2 | ||
5 | select * from test_innodb_read where id=2 | 3 |
SessionA在時(shí)間點(diǎn) 5 查看數(shù)據(jù)拿到的是 3 而不是 2,原因是,事務(wù)在對(duì)數(shù)據(jù)進(jìn)行更新操作時(shí)(時(shí)間點(diǎn)4),會(huì)先讀取一次數(shù)據(jù),這次讀取的不是事務(wù)開始版本,而是數(shù)據(jù)的最新提交的值 2。如果不讀取最新數(shù)據(jù)的話,就等于覆蓋了SessionB的更新,所以讀到的是 2,最后得到的數(shù)據(jù)是 3。
最后當(dāng)我知道這個(gè)知識(shí)點(diǎn)后,感覺背后一涼,以前寫代碼的時(shí)候,喜歡在事務(wù)里先把數(shù)據(jù)查出來,內(nèi)存中相加減,再存庫,現(xiàn)在想想這樣做就是BUG啊,坑...
不得不說,極客時(shí)間上面的這個(gè)MySQL課程還是很值的,至少讓我推翻了以前的想法
MySQL實(shí)戰(zhàn)45講-8 事務(wù)到底是隔離的還是不隔離的
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/17871.html
摘要:這里有點(diǎn)像的主從同步一樣,拿到內(nèi)存的最后版本后還有新過來的寫操作進(jìn)入和隊(duì)列,先把歷史版本推給客戶端,再把之后的寫操作一次推給客戶端。 本文是野狗科技聯(lián)合創(chuàng)始人&架構(gòu)師謝喬在ArchSummit 北京2015全球架構(gòu)師峰會(huì)上進(jìn)行的《基于數(shù)據(jù)同步云服務(wù)架構(gòu)實(shí)踐》的演講實(shí)錄,主要分為三個(gè)方面:野狗的數(shù)據(jù)同步理念,數(shù)據(jù)同步的架構(gòu)演進(jìn),數(shù)據(jù)同步的細(xì)節(jié)問題。野狗官博:https://blog.wi...
摘要:黑客技術(shù)點(diǎn)擊右側(cè)關(guān)注,了解黑客的世界開發(fā)進(jìn)階點(diǎn)擊右側(cè)關(guān)注,掌握進(jìn)階之路開發(fā)點(diǎn)擊右側(cè)關(guān)注,探討技術(shù)話題作者丨呼延十排版丨團(tuán)長(zhǎng)前言本文主要受眾為開發(fā)人員所以不涉及到的服務(wù)部署等操作且內(nèi)容較多大家準(zhǔn)備好耐心和瓜子礦泉水前一陣系統(tǒng)的學(xué)習(xí)了一下也有 ...
閱讀 676·2021-11-24 09:39
閱讀 2343·2021-11-22 13:54
閱讀 2211·2021-09-23 11:46
閱讀 3257·2019-08-30 15:55
閱讀 2692·2019-08-30 15:54
閱讀 2419·2019-08-30 14:18
閱讀 1556·2019-08-29 14:15
閱讀 2745·2019-08-29 13:49