MySql 事務隔離級別
事務隔離級別 | 臟讀 | 不可重復讀 | 幻讀 |
讀未提交(read-uncommitted) | 是 | 是 | 是 |
讀已提交(read-committed) | 否 | 是 | 是 |
可重復讀(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
1、臟讀:事務A讀取了事務B更新的數據,然后B回滾操作,那么A讀取到的數據是臟數據
2、不可重復讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果 不一致。
3、幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束后發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。
小結:不可重復讀的和幻讀很容易混淆,不可重復讀側重於修改,幻讀側重於新增或刪除。解決不可重復讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表
MySql默認事務隔離級別是:可重復讀(repeatable-read)
在Oracle,SqlServer中都是選擇讀已提交(Read Commited)作為默認的隔離級別
問題:為什么MySql默認設置的事務隔離級別是可重復讀?
答:這要從主從復制說起,主從復制是基於binlog復制的。binlog主要有3種格式:
- statement:記錄的是修改SQL語句
- row:記錄的是每行實際數據的變更
- mixed:statement和row模式的混合
Mysql在5.0這個版本以前,binlog只支持STATEMENT
這種格式!而這種格式在讀已提交(Read Commited)這個隔離級別下主從復制是有bug的,因此Mysql將可重復讀(Repeatable Read)作為默認的隔離級別!
5.1以后MySQL引入ROW格式,可以按行復制。因此由於歷史原因,mysql將默認的隔離級別設為可重復讀(Repeatable Read),保證主從復制不出問題!
項目中是不用讀未提交(Read UnCommitted)和串行化(Serializable)兩個隔離級別,原因有二
- 采用讀未提交(Read UnCommitted),一個事務讀到另一個事務未提交讀數據,這個不用多說吧,從邏輯上都說不過去!
- 采用串行化(Serializable),每個次讀操作都會加鎖,快照讀失效,一般是使用mysql自帶分布式事務功能時才使用該隔離級別!(因為這是XA事務,是強一致性事務,性能不佳!互聯網的分布式方案,多采用最終一致性的事務解決方案!)