參考文獻: 互聯網項目中mysql應該選什么事務隔離級別
歷史bug
mysql的默認隔離級別是可重復讀, 是為了兼容歷史bug, 目前該bug已經修復:
Mysql在5.0這個版本以前,binlog只支持STATEMENT這種格式!而這種格式在讀已提交(Read Commited)這個隔離級別下主從復制是有bug的,因此Mysql將可重復讀(Repeatable Read)作為默認的隔離級別!
將binglog的格式修改為row格式,此時是基于行的復制,自然就不會出現sql執行順序不一樣的問題!奈何這個格式在mysql5.1版本開始才引入。因此由于歷史原因,mysql將默認的隔離級別設為可重復讀(Repeatable Read),保證主從復制不出問題!
選擇讀已提交的原因
為了便于描述,下面將:
可重復讀(Repeatable Read),簡稱為RR;
讀已提交(Read Commited),簡稱為RC;
緣由一:在RR隔離級別下,存在間隙鎖,導致出現死鎖的幾率比RC大的多!
緣由二:在RR隔離級別下,條件列未命中索引會鎖表!而在RC隔離級別下,只鎖行!
緣由三:在RC隔離級別下,半一致性讀(semi-consistent)特性增加了update操作的并發性!
總之就想說明, RC的并發性高于RR.
2個疑問
- 在RC級別下,不可重復讀問題需要解決么?
不用解決,這個問題是可以接受的!畢竟你數據都已經提交了,讀出來本身就沒有太大問題!Oracle的默認隔離級別就是RC,你們改過Oracle的默認隔離級別么?
據我在金融機構的工作經歷, 使用RC才是正確的行為, 這樣可以察覺到其他并發事務的提交, 這樣才能保證在更新金額時拿到其他事務修改后的值.
樂觀鎖是另外一回事, 一般用在2個用戶在2個瀏覽器上修改同一個數據的時候, 有一個先查詢, 再修改的過程. 且查詢和修改各自都是短事務.
- 在RC級別下,主從復制用什么binlog格式?
OK,在該隔離級別下,用的binlog為row格式,是基于行的復制!Innodb的創始人也是建議binlog使用該格式!
總結
本文啰里八嗦了一篇文章只是為了說明一件事,互聯網項目請用:讀已提交(Read Commited)這個隔離級別!