MySQL 預設隔離級別是RR,為什麼阿里等大廠會改成RC?
阿新 • • 發佈:2021-11-22
我之前寫過一篇文章《為什麼MySQL選擇REPEATABLE READ作為預設隔離級別?》介紹過MySQL 的預設隔離級別是 Repeatable Reads以及背後的原因。
主要是因為MySQL在主從複製的過程是通過bin log 進行資料同步的,而MySQL早期只有statement這種bin log格式,這種格式下,bin log記錄的是SQL語句的原文。
當出現事務亂序的時候,就會導致備庫在 SQL 回放之後,結果和主庫內容不一致。
為了解決這個問題,MySQL採用了Repetable Read這種隔離級別,因為在 RR 中,會在更新資料的時候增加記錄鎖的同時增加間隙鎖。可以避免這種情況的發生。
關於MySQL的加鎖方式及加鎖原則,可以參考我寫的另外一篇《求你了,別再說資料庫鎖的只是索引了!》,這裡就不再贅述了。
在我知道MySQL 預設隔離級別是RR後,很長一段時間都以為應該不會有人去修改這個預設配置。
但是直到有一天,我們線上發生了一次死鎖的問題,我在排查的過程中,才發現我們的資料庫用的隔離級別沒有使用預設的 RR,而是修改成了Read Committed 。(關於那次死鎖排查過程,可以參考:一次資料庫的死鎖問題排查過程)
大家可以通過這個命令檢視資料庫當前的隔離級別:
select @@tx_isolation;
那麼,這裡不禁就有疑問了,為啥阿里要把這個資料庫隔離級別修改成 RC 呢,背後有什麼思考嗎?
RR 和 RC 的區別
想要搞清楚這個問題,我們需要先弄清楚 RR 和 RC 的區別,分析下各自的優缺點。
一致性讀
一致性讀,又稱為快照讀。快照即當前行資料之前的歷史版本。快照讀就是使用快照資訊顯示基於某個時間點的查詢結果,而不考慮與此同時執行的其他事務所執行的更改。
在MySQL 中,只有READ COMMITTED 和 REPEATABLE READ這兩種事務隔離級別才會使用一致性讀。
在 RC 中,每次讀取都會重新生成一個快照,總是讀取行的最新版本。
在 RR 中,快照會在事務中第一次SELECT語句執行時生成,只有在本事務中對資料進行更改才會更新快照。
在資料庫的 RC 這種隔離級別中,還支援"半一致讀" ,一條update語句,如果 where 條件匹配到的記錄已經加鎖,那麼InnoDB會返回記錄最近提交的版本,由MySQL上層判斷此是否需要真的加鎖。
鎖機制
資料庫的鎖,在不同的事務隔離級別下,是採用了不同的機制的。在 MySQL 中,有三種類型的鎖,分別是Record Lock、Gap Lock和 Next-Key Lock。 郭慕榮部落格園