標籤:
1. 資料庫事務ACID特性
資料庫事務的4個特性:
原子性(Atomic): 事務中的操作,要麼都成功或者都失敗; All or Nothing.
一致性(Consistency): 事務操作之後, 資料庫所處的狀態和商務規則是一致的; 比如a,b賬戶相互轉賬之後,總金額不變;
隔離性(Isolation): 多個事務之間就像是串列執行一樣,不相互影響;
持久性(Durability): 事務提交後被持久化到永久儲存.
2. 隔離性
其中 隔離性 分為了四種:
READ UNCOMMITTED:可以讀取未提交的資料,未提交的資料稱為髒資料,所以又稱髒讀。此時:幻讀,不可重複讀取和髒讀均允許;
READ COMMITTED:只能讀取已經提交的資料;此時:允許幻讀和不可重複讀取,但不允許髒讀,所以RC隔離等級要求解決髒讀;
REPEATABLE READ:同一個事務中多次執行同一個select,讀取到的資料沒有發生改變;此時:允許幻讀,但不允許不可重複讀取和髒讀,所以RR隔離等級要求解決不可重複讀取;
SERIALIZABLE: 幻讀,不可重複讀取和髒讀都不允許,所以serializable要求解決幻讀;
3. 幾個概念
髒讀:可以讀取未提交的資料。RC 要求解決髒讀;
不可重複讀取:同一個事務中多次執行同一個select, 讀取到的資料發生了改變(被其它事務update並且提交);
可重複讀:同一個事務中多次執行同一個select, 讀取到的資料沒有發生改變(一般使用MVCC實現);RR各級層級要求達到可重複讀的標準;
幻讀:同一個事務中多次執行同一個select, 讀取到的資料行發生改變。也就是行數減少或者增加了(被其它事務delete/insert並且提交)。SERIALIZABLE要求解決幻讀問題;
這裡一定要區分 不可重複讀取 和 幻讀:
不可重複讀取的重點是修改:
同樣的條件的select, 你讀取過的資料, 再次讀取出來發現值不一樣了
幻讀的重點在於新增或者刪除:
同樣的條件的select, 第1次和第2次讀出來的記錄數不一樣
從結果上來看, 兩者都是為多次讀取的結果不一致。但如果你從實現的角度來看, 它們的區別就比較大:
對於前者, 在RC下只需要鎖住滿足條件的記錄,就可以避免被其它事務修改,也就是 select for update, select in share mode; RR隔離下使用MVCC實現可重複讀;
對於後者, 要鎖住滿足條件的記錄及所有這些記錄之間的gap,也就是需要 gap lock。
而ANSI SQL標準沒有從隔離程度進行定義,而是定義了事務的隔離等級,同時定義了不同交易隔離等級解決的三大並發問題:
Isolation Level |
Dirty Read |
Unrepeatable Read |
Phantom Read |
Read UNCOMMITTED |
YES |
YES |
YES |
READ COMMITTED |
NO |
YES |
YES |
READ REPEATABLE |
NO |
NO |
YES |
SERIALIZABLE |
NO |
NO |
NO |
4. 資料庫的預設隔離等級
除了MySQL預設採用RR隔離等級之外,其它幾大資料庫都是採用RC隔離等級。
但是他們的實現也是極其不一樣的。Oracle僅僅實現了RC 和 SERIALIZABLE隔離等級。預設採用RC隔離等級,解決了髒讀。但是允許不可重複讀取和幻讀。其SERIALIZABLE則解決了髒讀、不可重複讀取、幻讀。
MySQL的實現:MySQL預設採用RR隔離等級,SQL標準是要求RR解決不可重複讀取的問題,但是因為MySQL採用了gap lock,所以實際上MySQL的RR隔離等級也解決了幻讀的問題。那麼MySQL的SERIALIZABLE是怎麼回事呢?其實MySQL的SERIALIZABLE採用了經典的實現方式,對讀和寫都加鎖。
那麼MySQL的RR隔離等級是如何解決不可重複讀取和幻讀的呢?
5. MySQL 中RC和RR隔離等級的區別
地方
MySQL RC 與 RR 的區別