標準隔離級別 讀未提交、讀已提交、可重覆讀、串列化 串列化 對事務中所有讀寫的數據加上讀鎖、寫鎖、範圍鎖。所以衝突的事務必須同步執行。 //console1 start transaction ; select * from transaction_test where `key`=1; updat ...
標準隔離級別
讀未提交、讀已提交、可重覆讀、串列化串列化
對事務中所有讀寫的數據加上讀鎖、寫鎖、範圍鎖。所以衝突的事務必須同步執行。//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