標準隔離級別
讀未提交、讀已提交、可重復讀、串行化串行化
對事務中所有讀寫的資料加上讀鎖、寫鎖、范圍鎖,所以沖突的事務必須同步執行,//console1 start transaction ; select * from transaction_test where `key`=1; update transaction_test set name='newTest' where `key`=1; //console2 start transaction ; select * from transaction_test where `key`=1;(由于事務1沒有釋放寫鎖,所以這里的查詢會阻塞 如果等待時間過長,會報如下的錯誤;如果事務1只是查詢,那么事務2也可以查詢) [40001][1205] Lock wait timeout exceeded; try restarting transaction //console1 commit ;(提交完之后如果事務2沒有等待超時,那么會立即執行) //console2; commit ;
可重復讀
核心是只對事務中所有讀寫的資料加上讀鎖、寫鎖,不加范圍鎖, 相比于讀已提交,由于對整個事務都加上了讀鎖,避免其他事務可以進行更新,進而保證同一個事務多次讀到的資料都是沒有被修改過的資料,----避免可重復讀---- name初始值為init //console1 start transaction ; select * from transaction_test where `key`=1;(查詢結果是init) //console2 start transaction ; update transaction_test set name='test' where `key`=1; (理論上,由于事務1已經獲取了讀鎖,事務2這里添加寫鎖應該是添加不上的,應該是阻塞中才對; 但是,實操發現,執行成功了,且在事務2中通過下面這個陳述句查詢是test,這應該也是mvcc導致的 select * from transaction_test where `key`=1; //console1 select * from transaction_test where `key`=1; console1的第2次查詢,查詢結果和第一次一樣,還是init 另外,事務2都獲得寫鎖了,怎么能允許你事務1再去獲得讀鎖 commit ; //console2 commit ;相比于串行化,由于沒有加范圍鎖,會引發一種叫幻讀的情況 所謂幻讀是指在同一個事務中,第一次查詢id<10的假定有1條,第二次查詢可能會有2條,原因是在兩次查詢的中間,存在別的事務插入或者洗掉了資料,由于事務A只加了讀鎖或者寫鎖,只能防止其他事務對已經加鎖的這幾條資料進行修改,但避免不了插入和洗掉,所以才會出現這個問題,
----幻讀---- 初始是1,name //console1 start transaction ; select * from transaction_test where `key`<10; //console2 start transaction ; insert into transaction_test ( `key`,`name`) value (3,'newddd'); select * from transaction_test where `key`<10; commit; //console1 select * from transaction_test where `key`<10; 理論上來講,這個地方應該會查到三條,但是實操發現,在事務2添加并提交之后,事務1查到了依然是原來的樣子 commit ; select * from transaction_test where `key`<10;(提交之后再次查詢就有新結果了)
讀已提交
核心是對事務中需要更新的操作行加寫鎖,直到事務結束,但對查詢的操作行加讀鎖,但在查詢完之后立即釋放,即不是在整個事務范圍鎖定, 讀已提交通過對查詢操作加鎖來避免讀未提交,在事務B修改資料時因為其在事務結束之前一直持有寫鎖,事務A無法對資料加讀鎖,只能等待事務B提交事務才可以讀取,這也是讀已提交的名稱的由來, 雖然解決了讀未提交的問題,但是由于只在查詢的時候短暫加了寫鎖,引發了另一個不可重復讀的問題; 所謂不可重復讀是指在同一個事務中,對于同樣一條資料的兩次查詢結果不一樣,那么這個和幻讀有什么區別呢?幻讀整個事務中都存在讀鎖或者寫鎖,其他事務無法修改,只能增刪;但是不可重復讀,則是指當前已經查到的結果被更新了, 原因是假如同一個事務兩次查詢中間,別的事務進行了修改,由于事務A沒有加整個事務范圍的讀鎖,所以事務B是可以成功獲取寫鎖的,進而修改資料,最終導致了不可重復讀,---避免讀未提交---- name初始值是init //console1 start transaction ; select * from transaction_test where `key`=1; update transaction_test set name='test' where `key`=1; //console2 start transaction ; select * from transaction_test where `key`=1;(由于讀不到未提交的,所以肯定獲取不到修改后的test值,理論上只能等待事務1結束) 這個地方由于事務1已經添加了寫鎖,原則上事務2根本查詢不了,應該阻塞,就像串行化那里一樣 但是實際結果卻是可以查到以前的值,即init;所以這里應該是mvcc的作用 在讀已提交的級別下,mvcc機制總是取最新的版本即可,即最近被 Commit 的那個版本的資料記錄, 這樣保證了讀到的都是已提交的事務,且保留了幻讀問題 最新版本的快照讀,不是當前讀 //console1 commit;//提交之后,事務2再次查詢,發現已經可以獲取到改動后的值了,即test ---不可重復讀---- name初始值是init //console1 start transaction ; select * from transaction_test where `key`=1;(第一次查詢是init) //console2 start transaction ; update transaction_test set name='test' where `key`=1;(在事務2中更新并提交) commit ; //console1 select * from transaction_test where `key`=1;(第二次查詢是test) commit ;
讀未提交
核心是對事務中需要更新的操作行加寫鎖,直到事務結束,但對查詢的操作行不加鎖, 引發的問題是臟讀,其實就是讀到了其他事務還沒有提交的資料;那么為什么事務A可以讀到事務B還沒有提交的資料? 分為兩步理解: 1.為什么存在可以讀的新的資料? 核心原因應該是write-ahead logging的設計,即上一章提到的允許在事務提交之前提前寫入資料,理論上肯定是寫到了記憶體中,并且記錄到undolog里面,雖然還不太情況事務的提交真正干了什么操作,但目前來,在記憶體是可以讀到已經修改好的資料, 2.為什么可以讀到已經加了寫鎖的資料 原因是讀未提交讀取資料是不加讀鎖的,而寫鎖只能防止其他事物不能加讀鎖和寫鎖,而不能防止沒有鎖 也可以看一下這篇博客的解釋show variables like 'transaction%'; set global transaction isolation level read uncommitted ;//設定完之后要重新登錄 CREATE TABLE `transaction_test` ( `key` int(11), `name` varchar(10) DEFAULT NULL ) ENGINE=InnoDB; ---read uncommitted--- 讀未提交 //console1 start transaction ; insert into transaction_test value (1,'test'); //console2 start transaction ; select * from transaction_test where `key`=1; (查詢結果為1,test) //console1 commit ; //console2 commit; 兩個事務都是寫事務,晚開啟的事務更新會阻塞 //console1 start transaction ; update transaction_test set name='newTest' where `key`=1; //console2 start transaction ; update transaction_test set name='Test' where `key`=1;(會阻塞,一直在執行中) //console1 commit ;(在事務1提交成功后,事務2的更新立馬就成功了) //console2 commit;
參考資料:
12 | 本地事務如何實作隔離性?-極客時間 03 | 事務隔離:為什么你改了我還看不見?-極客時間 讀未提交-為什么事務沒提交就可以讀到別人修改的資料 - 秦一居 - 博客園本文來自博客園,作者:起司啊,轉載請注明原文鏈接:https://www.cnblogs.com/qisi/p/transaction_isolation_level.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/554830.html
標籤:MySQL
下一篇:返回列表