爲何mysql默認隔離級別設置爲可重複讀

通常的DBMS系統,默認都會使用讀提交(Read-Comitted,RC)做爲默認隔離級別,如Oracle、SQLServer等,而MySQL卻使用可重複讀(Read-Repeatable,RR)。要知道,越高的隔離級別,能解決的數據一致性問題越多,理論上性能損耗更大,可併發性越低。隔離級別依次爲>:串行化 > RR > RC >讀未提交mysql

在SQL標準中,前三種隔離級別分別解決了幻象讀、不可重複讀和髒讀的問題。那麼,爲何MySQL使用可重複讀做爲默認隔離級別呢?
這個是有歷史緣由的,要從主從複製開始講起了!
1.主從複製,是基於什麼複製的?
是基於binlog複製的
2.binlog有幾種格式?
statement:記錄的是修改SQL語句
row:記錄的是每行實際數據的變動
mixed:statement和row模式的混合
那Mysql在5.0這個版本之前,binlog只支持STATEMENT這種格式!而這種格式在讀已提交(Read Commited)這個隔離級別下主從複製是有bug的,所以Mysql將可重複讀(Repeatable Read)做爲默認的隔離級別!
接下來,就要說說當binlog爲STATEMENT格式,且隔離級別爲讀已提交(Read Commited)時,有什麼bug呢?以下圖所示,在主(master)上執行以下事務:sql

此時在主庫中查詢:session

select * from t;
1
輸出結果:併發

+---+---+
| c1 |c2
+---+---+
| 2 | 2
+---+---+
1 row in set
1
2
3
4
5
6
從庫中查詢:性能

select * from t;
1
輸出結果:事務

Empty set
1
這裏出現了主從不一致性的問題!緣由其實很簡單,就是在master上執行的順序爲先刪後插!而此時binlog爲STATEMENT格式,它記錄的順序爲先插後刪!從(slave)同步的是binglog,所以從機執行的順序和主機不一致!就會出現主從不一致!
如何解決?
解決方案有兩種!
(1)隔離級別設爲可重複讀(Repeatable Read),在該隔離級別下引入間隙鎖。當Session 1執行delete語句時,會鎖住間隙。那麼,Ssession 2執行插入語句就會阻塞住!
(2)將binglog的格式修改成row格式,此時是基於行的複製,天然就不會出現sql執行順序不同的問題!奈何這個格式在mysql5.1版本開始才引入。
 同步

相關文章
相關標籤/搜索