1. 程式人生 > >3.事務級別

3.事務級別

一. ACID解釋

A: Atomicity 原子性
C: Consistencey 一致性
I: Isolation 一致性
D: Durability 永續性

二. 事務隔離級別
  1. 讀未提交(read uncommited)一個事務還未提交,它的更改可以被其他事務讀到。
  2. 讀提交(read commited)只有一個事務提交了後,它的更改才可以被其他事務讀到。
  3. 可重複讀(repeatable read)一個事務執行過程中看到的資料,總是跟這個事務啟動前看到的資料是一致的。當然在可重複讀隔離級別下,未提交變更對其他事務也是不可見的。
  4. 序列化(serializable)對於同一行記錄,讀會加讀鎖,寫會加寫鎖。當出現讀寫鎖衝突的時候,後訪問的事務必須等前一個事務執行完成。

知識點 讀提交和可重複讀的區別是:有兩個事務A,B。讀提交是:如果A事務在開啟過程中,B事務對記錄進行了更改並且提交了,A是可以讀到的B事務更改後的記錄。可重複讀則是:就算A事務在開啟過程中B事務對記錄進行了更改並且提交了,A也是讀不到B更改後的記錄。A事務仍然讀到的事它開啟時記錄最初的狀態。只有當A事務進行提交後才能讀到B更改後的記錄。

Oracle預設的隔離級別是讀提交
配置的方式是,將啟動引數 transaction-isolation 的值設定成READ-COMMITTED。你可以用 show variables 來檢視當前的值。

可重複讀的應用場景

假設你在管理一個個人銀行賬戶表。一個表存了每個月月底的餘額,一個表存了賬單明細。這時候你要做資料校對,也就是判斷上個月的餘額和當前餘額的差額,是否與本月的賬單明細一致。你一定希望在校對過程中,即使有使用者發生了一筆新的交易,也不影響你的校對結果。

三. 事務隔離實現為什麼要避免大量的大事務

在 MySQL 中,實際上每條記錄在更新的時候都會同時記錄一條回滾操作。記錄上的最新值,通過回滾操作,都可以得到前一個狀態的值。
假設一個值從 1 被按順序改成了 2、3、4,在回滾日誌裡面就會有類似下面的記錄。

graph RL
當前值4-->將4改成3; 
將4改成3-->將3改成2;
將3改成2-->將2改成1;

read_view_C-->無;
無-->read_view_B;
read_view_B-->read_view_A

當前值是 4,但是在查詢這條記錄的時候,不同時刻啟動的事務會有不同的 read-view。如圖中看到的,在檢視 A、B、C 裡面,這一個記錄的值分別是 1、2、4,同一條記錄在系統中可以存在多個版本,就是資料庫的多版本併發控制(MVCC)。對於 read-view A,要得到 1,就必須將當前值依次執行圖中所有的回滾操作得到。同時你會發現,即使現在有另外一個事務正在將 4 改成 5,這個事務跟 read-view A、B、C 對應的事務是不會衝突的。

當系統裡沒有比這個回滾日誌更早的 read-view 的時候才刪除日誌。
長事務意味著系統裡面會存在很老的事務檢視。由於這些事務隨時可能訪問資料庫裡面的任何資料,所以這個事務提交之前,資料庫裡面它可能用到的回滾記錄都必須保留,這就會導致大量佔用儲存空間。
除了對回滾段的影響,長事務還佔用鎖資源,也可能拖垮整個庫。
在工作中有的公司程式碼中可能採用的AOP來進行事務管理,根據service層入口的方法名字首來判斷是否開啟事務,經常能看到有的開發者為了不必要的麻煩所有都採用了開啟事務,這是不合理的。

摘自《極客時間》MySQL36講