記一次Mysql事務隔離級別的坑

最近在寫代碼調試時,遇到了一個問題。mysql

遇到問題

具體操做以下:
1.調用方法A,而且方法A加上了@Transactional事務註解。
2.在方法A內部,查詢並更新某個字段F的值。
3.處理其餘邏輯。
4.查詢並打印日誌,記錄關鍵字段的值,包括字段F。
5.方法A結束。
因爲剛剛接手這塊代碼,並且這個方法又寫得很長,因此不少邏輯都無法細看,只能慢慢調試。
我在第4步打了斷點,調試時查看日誌,感受數據有問題,將sql複製到數據庫裏面手動跑了一遍,
發現在方法裏和數據庫裏,執行同一條Sql,結果居然不同。
一開始還有點蒙圈,覺得是IDE的bug,多是緩存之類的問題。
而後又調試了幾遍,單步調試時觀察到手動在數據庫裏查出來的字段值,老是方法剛開始還未變動時的值
恍然才明白,原來是事務隔離級別形成的。面試

事務隔離級別

這些知識點,其實之前面試都背得倒背如流。如今時間久了,一會兒又忘光了。
Q:數據庫的隔離級別有哪些?
讀未提交(read-uncommitted)讀提交(read-committed) 可重複讀(repeatable-read)串行化(serializable)。
Q:mysql默認的數據庫隔離級別是什麼?
可重複讀(repeatable-read)sql

一致性非鎖定讀

Mysql採用INNODB存儲引擎。SELECT操做,使用一致性非鎖定讀。
在READ COMMITTED事務隔離級別下,對於快照數據,非一致性讀老是讀取被鎖定的行的最新一份快照數據。
在REPEATABLE READ(可重複讀)事務隔離級別下,對於快照數據,非一致性讀老是讀取事務開始時的行數據版本。
而我遇到的問題,就是說事務A開啓後,變動了數據,尚未提交,而後事務B就去進行查詢。
由於默認的REPEATABLE READ事務隔離級別,讀取到的是事務開始時的行數據版本。數據庫

不一樣事務隔離級別可能出現的問題

1.髒讀
髒讀:髒數據是指未提交的數據。髒讀是指在不一樣的事務下,當前事務能夠讀到另外事務未提交的數據。這顯然違反了數據庫的隔離性。
髒讀發生的事務隔離級別:READ UNCOMMITED。
2.不可重複讀
不可重複讀:在一個事務內兩次讀到的數據不同。好比,A事務尚未結束,B事務對同一數據進行修改,因爲B事務的修改,那麼A事務兩次讀到的數據是不同的。違背了數據庫事務一致性的要求。
不可重複讀,讀到的是已經提交的數據。
不可重複讀,發生的隔離級別是READ COMMITTED。
3.幻讀:A事務讀取了B事務已經提交的新增數據。
4.丟失更新
丟失更新,是指一個事務的更新操做會被另外一個事務的更新操做覆蓋。緩存

參考資料:《Mysql技術內幕》調試

相關文章
相關標籤/搜索