MySQL數據庫的默認隔離級別為什么是可重復讀


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

在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)上執行如下事務:

此時在主庫中查詢:

select * from t;

輸出結果:

+---+---+
| c1 |c2
+---+---+
| 2 | 2
+---+---+
1 row in set
從庫中查詢:

select * from t;

輸出結果:

Empty set

這里出現了主從不一致性的問題!原因其實很簡單,就是在master上執行的順序為先刪后插!而此時binlog為STATEMENT格式,它記錄的順序為先插后刪!從(slave)同步的是binglog,因此從機執行的順序和主機不一致!就會出現主從不一致!

如何解決?

解決方案有兩種!

(1)隔離級別設為可重復讀(Repeatable Read),在該隔離級別下引入間隙鎖。當Session 1執行delete語句時,會鎖住間隙。那么,Ssession 2執行插入語句就會阻塞住!

(2)將binglog的格式修改為row格式,此時是基於行的復制,自然就不會出現sql執行順序不一樣的問題!奈何這個格式在mysql5.1版本開始才引入。

因此由於歷史原因,mysql將默認的隔離級別設為可重復讀(Repeatable Read),保證主從復制不出問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM