亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

詳解MySQL 幻讀及如何消除

瀏覽:6日期:2023-10-04 11:37:19

這是一篇數(shù)據(jù)庫隔離級別的科普文章,旨在了解數(shù)據(jù)庫中著名的幻讀現(xiàn)象,為了專注,對臟讀、不可重復(fù)讀不作討論。

事務(wù)隔離級別

MySQL有四級事務(wù)隔離級別:

讀未提交 READ-UNCOMMITTED: 存在臟讀,不可重復(fù)讀,幻讀的問題讀已提交 READ-COMMITTED:不存在臟讀,但存在不可重復(fù)讀,幻讀問題可重復(fù)讀 REPEATABLE-READ:不存在臟讀,不可重復(fù)讀問題,但存在幻讀問題序列化SERIALIZABLE:解決臟讀,不可重復(fù)讀,幻讀問題,但完全串行執(zhí)行,性能最低

什么是幻讀

幻讀錯誤的理解:說幻讀是事務(wù)A 執(zhí)行兩次 select 操作得到不同的數(shù)據(jù)集,即 select 1 得到10條記錄,select 2 得到11條記錄。這其實并不是幻讀,這是不可重復(fù)讀的一種,只會在 R-U R-C 級別下出現(xiàn),而在 mysql 默認的 RR 隔離級別是不會出現(xiàn)的。

這里給出我對幻讀的理解:

幻讀,并不是說事務(wù)中多次讀取獲取的結(jié)果集不同,幻讀更重要的是某次的 select 操作得到的結(jié)果集所表征的數(shù)據(jù)狀態(tài)無法支撐后續(xù)的業(yè)務(wù)操作。更為具體一些:select 記錄不存在,準備插入此記錄,但執(zhí)行 insert 時發(fā)現(xiàn)此記錄已存在,無法插入,如同產(chǎn)生了幻覺

舉個例子可能會簡化理解:

mysql> show create table userG*************************** 1. row *************************** Table: userCreate Table: CREATE TABLE `user` ( `id` int(11) NOT NULL, `name` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8

分別開啟兩個事務(wù)T1 & T2,并設(shè)置其隔離級別為Reaptable-Read:

T1:

mysql> set global transaction isolation level repeatable read; ​mysql> begin;mysql> select * from user;mysql> insert into user values (1, ’jeff’);ERROR 1062 (23000): Duplicate entry ’1’ for key ’PRIMARY’​mysql> select * from user;

T2:

mysql> set global transaction isolation level repeatable read; ​mysql> begin;mysql> insert into user values (1, ’jeff’);mysql> commit;

T1 事務(wù)檢測表中是否有 id 為 1 的記錄,沒有則插入

T2 插入干擾記錄,造成T1出現(xiàn)幻讀。

上例中需要確保T1事務(wù)執(zhí)行begin后才開始執(zhí)行事務(wù)T2。

上例中T1就發(fā)生了幻讀,因為 T1讀取的數(shù)據(jù)狀態(tài)與后面的動作發(fā)生了語義上的沖突:查詢的時候明明提示記錄不存在,插入的時候去提示主鍵重復(fù),類似于出現(xiàn)幻影,因而稱之為幻讀。

如何消除幻讀

MySQL當(dāng)前有兩種方式可以消除幻讀:

1. 通過對select操作手動加行X鎖(SELECT ... FOR UPDATE )。原因是InnoDB中行鎖鎖定的是索引,縱然當(dāng)前記錄不存在,當(dāng)前事務(wù)也會獲得一把記錄鎖(記錄存在就加行X鎖,不存在就加next-key lock間隙X鎖),這樣其他事務(wù)則無法插入此索引的記錄,杜絕幻讀。2. 進一步提升隔離級別為SERIALIZABLE測試一下效果

mysql> begin;​mysql> select * from user where id = 2 for update;mysql> insert into user values (2, ’tony’);mysql> commit;

T2:

mysql> begin;​mysql> insert into user values (2, ’jimmy’);ERROR 1062 (23000): Duplicate entry ’2’ for key ’PRIMARY’

現(xiàn)在T1查詢時攜帶了for update,在Innodb內(nèi)會對該索引加鎖(即使當(dāng)前不存在),于是事務(wù)T2的insert會被阻塞直到T1顯示提交,這樣T1成功了,對于T1來說,幻讀確實被消除了,但T2的插入會報主鍵重復(fù),這也符合預(yù)期。

至于另外一種提升隔離級別消除幻讀的方式感興趣的可以自己嘗試,這里不再重復(fù),其本質(zhì)是類似的,只是讓系統(tǒng)代替了手工加鎖。

總結(jié)

RR作為 mysql 事務(wù)默認隔離級別,是事務(wù)安全與性能的折中,正確認識幻讀后,開發(fā)者便可以根據(jù)需求自行決定是否需要防止幻讀。

SERIALIZABLE則是悲觀的認為幻讀時刻都會發(fā)生,故會自動的隱式的對事務(wù)所需資源加排它鎖,其他事務(wù)訪問此資源會被阻塞等待,故事務(wù)是安全的,但需要認真考慮性能。

InnoDB的鎖是針對索引,這點需要引起注意。對行記錄加鎖,如果存在,加X鎖,否則會加 next-key lock / gap 鎖 / 間隙鎖,故InnoDB可以實現(xiàn)事務(wù)對某記錄的預(yù)先占用,只要本事務(wù)還在,其他事務(wù)就別想占有它。關(guān)于鎖,后面還會再有專門的文章討論。

以上就是詳解MySQL 幻讀及如何消除的詳細內(nèi)容,更多關(guān)于MySQL 幻讀及消除的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

相關(guān)文章:
主站蜘蛛池模板: 在线欧美日韩国产 | 黄片一级毛片 | 国产羞羞视频在线观看 | 日本一区二区三区日本免费 | 特级aa一级欧美毛片 | 妞干网视频在线观看 | 蜜芽亚洲| 亚洲一区二区三区免费视频 | 免费看黄色片网站 | 色啊色 | 欧美日韩无线在码不卡一区二区三区 | 国产成人综合网在线播放 | 人人综合 | 黄色午夜 | 日韩欧美二区在线观看 | 午夜a视频| 亚洲国产精品v在线播放 | 国产精品视频永久免费播放 | 拍拍拍精品视频在线观看 | 精品久久一 | 亚洲一区二区三区四区五区 | 蛇女欲潮三级在线看 | 亚洲精品日韩精品一区 | 精品国产高清毛片 | 国产一级c片 | 丁香啪啪天堂激情婷婷 | 国产欧美精品一区二区三区-老狼 | 久久99国产一区二区三区 | 精品久久久久久亚洲 | 天天爽影院一区二区在线影院 | 一本黄色片 | 色视频亚洲 | a级国产视频 | 欧美在线视频二区 | 欧美成人免费在线观看 | 91亚洲区国产区精品区 | 国产精品视频在线免费观看 | 999精品久久久中文字幕蜜桃 | 国产伦精品一区二区三区视频小说 | 久久精品成人一区二区三区 | 欧美日韩一卡 |