做者介紹: 趙偉 騰訊雲TDSQL數據庫開發者mysql
MySQL (這裏的MySQL是指廣義的mysql,包括oracle,mysql,percona,mariadb等)的Statement Based Replication (SBR)是一個暗坑無數的功能,可能致使主備機數據不一致,以及其它問題,因此在TDSQL中咱們使用RBR。這裏就列舉幾條SBR的坑。sql
在此以前,先說說SBR的有點。與Row based Replication (RBR)相比,它能夠避免傳輸大量的binlog日誌從而減少網絡和存儲系統(binlog文件)的負載。另外,某些時候在備機上面從新執行SQL語句反而會比逐條執行RBR的binlog要快,一個極端的例子是,若是一個表沒有主鍵,而後一個delete/update語句須要刪除/更新大量的行,那麼使用RBR將是噩夢,由於備機處理每一條這樣的binlog都會致使全表掃描從而大大下降備機的性能(因此在TDSQL中咱們默認強制建立含有主鍵的表)。可是使用SBR的話,一次執行便可更新/刪除所有行,這樣就快了不少。數據庫
下面正式開始批評SBR了。網絡
首先,因爲SBR模式下,SQL語句到了備機須要被從新執行,與RBR相比,就增長了從新執行SQL語句的額外開銷,包括解析,優化和執行SQL語句。RBR則直接調用mysql的存儲引擎接口(handler API)來執行行的插入、刪除和更新,徹底跳過了mysql的優化器的處理邏輯。架構
SQL語句到了備機須要被從新執行,在多種狀況下就會致使主備機數據不一致,好比一個SQL語句調用了用戶定義的函數,調用了返回隨機值的函數,在數據表中使用了自增列,以及使用了上下文數據(context data,好比用一個表的行數做爲某個插入字段值,或者在update/delete
語句中使用了limit子句)等等。併發
另外一個一致性陷阱在於使用MyISAM等非事務存儲引擎。在徹底使用innodb等事務存儲引擎的狀況下,MySQL replication是crash safe
的,也就是說,不管任什麼時候刻mysql server crash了,或者OS crash了,或者機器斷電了,mysql server均可以恢復數據到crash以前的狀態,確保事務的持久性和一致性,確保全部以前提交的事務的改動都存在,由於innodb自身支持事務,能夠恢復,而且在近年版本的mysql和mariadb中,innodb可使用到binlog數據來完成恢復。(儘管組提交時候並無刷盤commit日誌) 可是一旦使用了非事務存儲引擎,那麼一個事務的完整性就不存在了,也不是crash safe的了。在master和slave上面都是這樣。雖然mysql的各個分支和版本在replication實現中作了不少努力來避免一些問題,而且給用戶強制了一大堆暗坑無數的DOs&DONTs,可是沒法徹底解決這個問題。當發生了crash以後,只要一個事務讀取 而且/或者 寫入到了MyISAM表,那麼這個事務的改動可能部分存在,部分消失,而且binlog與數據表也可能會有各類不一樣,而後,用戶的數據就沒法使用了。oracle
第三,在使用innodb/xtradb而且隔離級別是read committed時候,若是設置binlog_format爲statement,那麼mysql會拒絕後續的插入/更新/刪除操做,錯誤信息是:函數
ERROR 1665 (HY000): Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.
性能
可是在設置這兩個變量的時候卻並無報錯。這個組合也是會致使slave在併發執行時候的數據一致性問題。 因此,仍是推薦你們使用RBR和INNODB(或者其餘支持事務的存儲引擎)的搭配,咱們一直用它:)優化
此文已由做者受權騰訊雲技術社區發佈,轉載請註明文章出處,獲取更多雲計算技術乾貨,可請前往騰訊雲技術社區
歡迎你們關注騰訊雲技術社區-博客園官方主頁,咱們將持續在博客園爲你們推薦技術精品文章哦~