【MySQL】MySQL5.6新特性之crash-safe

楊奇龍發表於2015-07-26
一 介紹
  MySQL 5.6 針對複製功能提供了新特性: slave支援crash-safe. 該功能可以解決之前版本中系統異常斷電可能導致的SQL thread 資訊不準確的問題。本文從原理方面對該特性進行介紹。
二 原理
  在瞭解crash-safe slave 之前,我們先分析一下MySQL 5.6 之前的版本出現 crash-unsafe 的原因。在slave上,複製包含兩個執行緒:即replication中的IO thread和SQL thread。
IO thread負責從master複製binlog檔案並儲存到本地,複製過來的binlog稱為relay-log. 
SQL thread負責執行relay-log.
兩個執行緒的執行進度(偏移量)都儲存在檔案中.IO thread的執行狀態資訊儲存在master.info檔案,SQL thread的執行狀態資訊儲存在relay-log.info檔案。系統執行正常的情況下,這種模式到目前為止還沒有問題。需要注意的是這些檔案被修改後不是同步寫入磁碟的,每當系統發生crash,儲存的偏移量可能都不準確.MySQL 5.5透過兩個引數修復了該問題,使用sync_master_info=1和sync_replay_log_info=1 來保證Slave 的兩個執行緒每次寫一個事務就分別向兩個檔案同步一次 IO thread和SQL thread當前執行的資訊。當然同步操作不是免費的,頻繁更新磁碟檔案需要消耗效能,如果你的RAID裝置的IO策略設定為WRITEBACK 模式,那麼這種方法便可以接受的。
 但是,即使設定了sync_master_info=1和sync_relay_info=1, 問題還是會出現,因為複製資訊是在transactions提交後寫入的,如果crash發生在事務提交和OS寫檔案之間,那麼relay-log.info就可能是錯誤的。當slave從新啟動的時候,最後那個事務可能會被執行兩次.具體的影響取決於事務的具體操作.複製可能會繼續執行比如update/delete,或者報錯 比如insert操作,此時主從資料的一致性可能會被破壞。
 MySQL 5.6版本透過將複製資訊存放到表中來解決此問題.透過配置兩個引數 relay_log_info_repository=TABLE,master_info_repository=TABLE,relay log info 會存放到 mysql.slave_relay_log_info表中,master info 會存放mysql.slave_master_info表中。就是把SQL執行緒執行事務和更新mysql.slave_replay_log_info的語句看成一個事務處理,這樣就會一直同步的.
我們可以透過虛擬碼來了解crash-safe 的原理
crash-unsafe情況下 SQL_thread 的 的工作模式
  1. START TRANSACTION;
  2.  Statement 1
  3.   ...
  4.  Statement N
  5.  COMMIT;
  6. Update replication info files
crash-safe情況下 SQL_thread 的 的工作模式
  1. START TRANSACTION;
  2.   Statement 1
  3.   ...
  4.   Statement N
  5.   Update replication info
  6. COMMIT
crash-safe就是將relay-info.log的資訊儲存在InnoDB的事務表中,這時執行relay log中的事務和寫relay info在一個事務中,就能得到原子性保證。從而避免已執行的binlog位點和寫入relay log info 的位點資訊不一致的情況發生。看到這裡也請各位讀者思考一下 ,現在的這種方案是否完美,有哪些問題?
 從上面的改變解決了SQL thread記錄執行狀態可能導致不一致的風險,但是對於IO thread 依然存在問題 。IO thread 從master上複製binlog寫入 relay log中,每個二進位制日誌由多個log event組成,所以每接收到一個log event就需要更新master-info.log而且該是寫入作業系統快取。從IO thread的工作原理來看,它沒有辦法 將寫入master info和拉取binlog放到同一個事務中而保持原子操作,因此IO thread 的行為是會對資料一致性會產生影響,設想一個log event傳送到了relay log中兩次的情形。如何解決呢?
 方案一 透過引數sync_master_info可以控制fdatasync的時間。預設值是10000,表示IO執行緒的偏移量每10000個事務更新一次 ,透過設定其為1,每寫一次事務便同步到master.info 。
 方案二 透過MySQL 5.5版本開始提供的引數relay_log_recovery ,當slave發生crash後重啟之後重連master時,slave不根據master-info.log的資訊進行重連,而是根據relay-info中執行到master的位置資訊重新開始拉master上的日誌資料。


三 如何使用 
  1 停止slave的mysql例項
  2 my.cnf檔案中新增
     master-info-repository=TABLE
     relay-log-info-repository=TABLE
     relay-log-recovery
  3 重啟slave的mysql例項
注意:
如果是MySQL 5.6.5 或者更早期。slave_master_info 和 slave_relay_log_info 表預設使用MyISAM 引擎。所以還得修改成innodb,如下:        
  1. ALTER TABLE mysql.slave_master_info ENGINE=InnoDB;
  2. ALTER TABLE mysql.slave_relay_log_info ENGINE=InnoDB
四 小結 
   MySQL 5.6 版本為MySQL的穩定性做出了很多改進,這點值得MySQL DBA 去關注,也值得大家去思考,這些改善點還有那些不足之處?有如何解決?

五 參考文章
 1 MySQL 5.6 Manual --slave logs  
 2 MySQL crash-safe replication  
 3 Enabling crash-safe slaves with MySQL 5.6 
 4 MySQL5.6 crash-safe replication一個坑
 5 Crash-safe Replication --推薦
 6 Better Crash-safe replication for MySQL

如果您覺得從這篇文章受益,可以贊助 北在南方 一瓶飲料 ^_^

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22664653/viewspace-1752588/,如需轉載,請註明出處,否則將追究法律責任。

相關文章