事務已提交另外會話查詢不到的問題解析

dbasdk發表於2017-02-25

作者:沃趣科技 葉秀慧


事務已提交另外會話查詢不到的問題解析

導讀:

今天遇到一個很有趣的問題:跑python程式碼程式,使用python程式開啟兩個session連線資料庫,在第二個sessiont表插入一行記錄,並commit了;在第一個session去查t表,發現t表中查詢不到剛插入的這條記錄記錄。而拿相同的python程式碼程式,在另一套環境上,也開啟2session,重複上面的操作,結果居然可以查到記錄。開發人員認為,我在session 2上資料都插入進去了,並且提交了,為什麼sessioin 1查詢不到?並且相同的程式碼,連的同一個mysql環境,怎麼兩次結果都不一樣? 

環境:

A環境:MySQL5.7.13 +相同的python程式碼+ Fedora22作業系統

B環境:MySQL5.7.13 +相同的python程式碼+ RedHat7作業系統

 

現象描述:

環境A的情況下,下面的實驗是模擬python程式碼程式跑的過程,如需使用python程式碼測試,詳見附錄3

 


 
結論:在環境A的情況下模擬,在session 1中無法搜到session2提交的變更。

在環境B的情況下,也去跑這個python指令碼,但是跑出來的結果如下:


結論:在環境
B的情況下模擬,在session 1中可以搜到session2提交的變更。 

 

問題分析:

隔離級別問題

  看到這樣的情況,我們理所當然的猜測,應該是隔離級別不同導致的,環境A的隔離級別應該是REPEATABLE-READ,可重複讀,什麼是REPEATABLE-READ?就是當你開啟一個事務,讀一個資料,而後再次讀,再讀,再讀……只要這個事務沒結束,那麼讀取的資料就是一致的。 所以,環境A下面,session1事務開啟,反覆查,結果是一致的,這很正常。

而環境B的隔離級別應該是READ-COMMITTED,提交讀,什麼是提交讀?就是隻要事務提交了,那你就能讀到修改的資料。所以,在環境B的情況下,session1第二次讀取的時候,就能讀到提交的資料。

 好了,現在去資料庫看下,是不是我們猜測的情況。

 
環境A




環境B


 

事實擺在眼前,結果出乎我們的意料。環境A和環境B都是REPEATABLE-READ,啊啊啊,那到底是為什麼呢?。

 

auto commit問題:

  明明是一模一樣的python程式碼,一樣的實驗環境,一樣mysql版本,一樣的執行過程,查詢到的結果就是不一致的?

唯一的不同,這2套環境的作業系統不一樣,環境AFedora22,環境Bredhat7,驗證中偶然發現,redhat7環境的autocommit變數居然還是on

預設情況下,python連線MySQL預設是自動開啟新事務,也就是說autocommit=OFF的。 

好,現在要引入一個MySQL引數,autocommit

什麼是autocommit

autocommit這個變數表示是否開啟自動提交事務模式。如果將這個值設定為1,那麼所有變更無需手工提交,每次提交SQL語句,事務就會自動提交,馬上生效。如果設定為0,那麼你必須使用commit來提交事務或者使用rollback來回滾事務,事務不會自動提交。

問題的原因最終確定:環境B是因為自動提交了事務,session1才在第二次搜尋的時候,查到了修改的資料。

詳細解釋一下環境A和環境B的現象:
環境A
環境AFedora22autocommit設定為0,表示已經關閉,隔離級別是REPEATABLE-READ。所以在session1中第二次搜尋t表的時候無法搜尋到新插入的資料,因為兩次搜尋都在一個事務裡面,實現了可重複讀。如果要搜到新提交的事務必須鍵入commit;才能搜尋到


環境B 
我們現在來分析情況環境B,環境BRedHat7autocommit設定為1,表示事務自動提交開啟,隔離級別是REPEATABLE-READ。所以對session1來說第二次去搜尋已經相當於已經是第二個事務了,當然就能搜尋得到session2提交的資料。


總結
 

提問:

透過上述的總結,各位看官可以嘗試回答幾個關於隔離級別的問題,來驗證下對隔離級別和自動事務提交引數的理解。

還是針對這2session



Q1.auto_commit=on,隔離級別是REPEATABLE-READT3時刻,session1能否看到session2T2時刻提交的資料? 

Q2.auto_commit=off,隔離級別是REPEATABLE-READT3時刻,session1能否看到session2T2時刻提交的資料?

Q3.auto_commit=on,隔離級別是READ-COMMITTEDT3時刻,session1能否看到session2T2時刻提交的資料?

Q4.auto_commit=off,隔離級別是READ-COMMITTEDT3時刻,session1能否看到session2T2時刻提交的資料?

 

回答:

Q1.能。

auto_commit=on,隔離級別是REPEATABLE-READsession1能看到session2T2時刻提交的資料。因為auto_commit=on的時候,每一個語句都是一個全新的事物,所以在T3的時候,session3作為一個新的事務是能查詢到,session2T2時刻提交的資料。

Q2.不能。

 auto_commit=off,隔離級別是REPEATABLE-READsession1不能看到session2T2時刻提交的資料。因為auto_commit=off的時候,對session1來說,在T3時刻,因為沒有提交,所以事務還是t1時候的那個事務,所以無法查到session2T2時刻提交的資料。

Q3.

auto_commit=on,隔離級別是READ-COMMITTEDsession1能看到session2T2時刻提交的資料。因為auto_commit=1的時候,每一個語句都是一個全新的事物,所以在T3的時候,session1作為一個新的事物是能查詢到,session2T2時刻提交的資料。

 

Q3.

auto_commit=off,隔離級別是READ-COMMITTEDsession1能看到session2T2時刻提交的資料。因為auto_commit=off的時候,雖然在T3的時候,session1還是T1時刻的那個事務,但是,READ-COMMITTED的特性就是可以看到已提交的事務。

 

 

 

附錄1:測試環境描述


附錄2:表結構


附錄3:python程式碼



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29734436/viewspace-2134267/,如需轉載,請註明出處,否則將追究法律責任。

相關文章