隔離級別 | 臟讀 | 不可重復讀 | 幻讀 |
讀未提交 | 可以出現 | 可以出現 | 可以出現 |
讀提交 | 不允許出現 | 可以出現 | 可以出現 |
可重復讀 | 不允許出現 | 不允許出現 | 可以出現 |
序列化 | 不允許出現 | 不允許出現 | 不允許出現 |
主要是讀已提交和可重復讀比較難區分,所以我們看個小例子。先創建一張表,并插入數據1
create database test; use test; create table test(id int primary key); insert into test(id) values(1);
事務A | 事務B |
啟動事務查詢得到1 | 啟動事務 |
查詢得到1 | |
將1改為2 | |
查詢得到V1 | |
提交事務B | |
查詢得到V2 | |
提交事務A | |
查詢得到V3 |
我們來看看在不同的隔離級別下,事務A會有哪些不同的返回結果,也就是圖里面V1、V2、V3的返回值分別是什么。
數據庫里面會創建一個視圖,訪問的時候以視圖的邏輯結果為準。在“可重復讀”隔離級別下,這個視圖是在事務啟 動時創建的,整個事務存在期間都用這個視圖。在“讀提交”隔離級別下,這個視圖是在每個SQL語句開始執行的時候創建的。 這里需要注意的是,“讀未提交”隔離級別下直接返回記錄上的最新值,沒有視圖概念;而“串行化”隔離級別下直接用加鎖的方式來避免并行訪問。
那什么時候需 要**“可重復讀”**的場景呢?
假設你在管理一個個人銀行賬戶表。一個表存了每個月月底的余額,一個表存了賬單明細。這時候你要做數據校對,也就是判斷上個月的余額和當前余額的差額,是否與本月的賬單明細一致。你一定希望在校對過程中,即使有用戶發生了一筆新的交 易,也不影響你的校對結果。
事務隔離的實現
在MySQL中,實際上每條記錄在更新的時候都會同時記錄一條回滾操作。記錄上的最新值,通過回滾操作,都可以得到前一個狀態的值。假設一個值從1被按順序改成了2、3、4,在回滾日志里面就會有類似下面的記錄。
當前值是4,但是在查詢這條記錄的時候,不同時刻啟動的事務會有不同的read-view。如圖中看到的,在視圖A、B、C里面, 這一個記錄的值分別是1、2、4,同一條記錄在系統中可以存在多個版本,就是數據庫的多版本并發控制(MVCC)。對于 read-view A,要得到1,就必須將當前值依次執行圖中所有的回滾操作得到。即使現在有另外一個事務正在將4改成5,這個事務跟read-view A、B、C對應的事務是不會沖突的。
回滾日志總不能一直保留吧,什么時候刪除呢?
在不需要的時候才刪除。也就是說,系統會判斷,當沒有事務再需要用到這些回滾日志時,回滾日志會被刪除。
什么時候才不需要了呢?
就是當系統里沒有比這個回滾日志更早的read-view的時候。
為什么盡量不要使用事務?
事務意味著系統里面會存在很老的事務視圖,在這個事務提交之前,回滾記錄都要保留, 這會導致大量占用存儲空間。除此之外,事務還占用鎖資源,可能會拖垮庫。
以上就是關于msyql事務隔離你要知道的詳細內容,更多關于mysql事務隔離的資料請關注腳本之家其它相關文章!