MySQL——主從復制
以前對 MySQL 作資料分布僅僅是讀寫分離,通過資料庫自身的主從復制即可實作寫主庫、讀從庫,現在則需要雙寫主庫并在經歷一個短暫的延時后達成最終一致性,這個問題乍一想比較復雜,但歸根結底還是資料最終一致性的問題,
一個資料庫資料一致性保證
資料庫的事務特性來保證的,具體見blog中《事務》,
主從架構之間資料一致性
MySQL 為了提供主從復制功能引入了一個新的日志檔案叫 binlog,它包含了引發資料變更的事件日志集合,從庫請求主庫發送 binlog 并通過日志事件還原資料寫入從庫,所以從庫的資料來源為 binlog,這樣 MySQL 主庫只需做到 binlog 與本地資料一致就可以保證主從庫資料一致(暫且忽略網路傳輸引發的主從不一致),我們知道保證本地資料一致性是靠資料庫事務特性來達成的,而資料庫事務是如何實作的呢?先看下面這張圖:

MySQL 本身不提供事務支持,而是開放了存盤引擎介面,由具體的存盤引擎來實作,具體來說支持 MySQL 事務的存盤引擎就是 InnoDB,存盤引擎實作事務的通用方式是基于 redo log 和 undo log,簡單來說,redo log 記錄事務修改后的資料, undo log 記錄事務前的原始資料,所以當一個事務執行時實際發生程序簡化描述如下:
- 先記錄 undo/redo log,確保日志刷到磁盤上持久存盤,
- 更新資料記錄,快取操作并異步刷盤,
- 提交事務,在 redo log 中寫入 commit 記錄,
在 MySQL 執行事務程序中如果因故障中斷,可以通過 redo log 來重做事務或通過 undo log 來回滾,確保了資料的一致性,這些都是由事務性存盤引擎來完成的,但 binlog 不在事務存盤引擎范圍內,而是由 MySQL Server 來記錄的,那么就必須保證 binlog 資料和 redo log 之間的一致性,所以開啟了 binlog 后實際的事務執行就多了一步,如下:
- 先記錄 undo/redo log,確保日志刷到磁盤上持久存盤,
- 更新資料記錄,快取操作并異步刷盤,
- 將事務日志持久化到 binlog,
- 提交事務,在 redo log 中寫入提交記錄,
這樣的話,只要 binlog 沒寫成功,整個事務是需要回滾的,而 binlog 寫成功后即使 MySQL Crash 了都可以恢復事務并完成提交,要做到這點,就需要把 binlog 和事務關聯起來,而只有保證了 binlog 和事務資料的一致性,才能保證主從資料的一致性,所以 binlog 的寫入程序不得不嵌入到純粹的事務存盤引擎執行程序中,并以內部分布式事務(xa 事務)的方式完成兩階段提交,
總結
我們前面先提出了一個問題,然后從資料一致性的角度去思考,參考了 MySQL 的實作方式,理清并分析了 MySQL 單機環境是如何保證復制機制的資料一致性,也就是 binlog 和事務資料的一致,后面我們才能基于 binlog 這個機制去實作復制并保證主從復制的一致性,主從復制又引入了網路因素,進一步增加了保證主從資料一致性的復雜度,后面還會撰文進一步分析這個問題,
參考資料
后端分布式系列:分布式存盤-MySQL 資料庫事務與復制
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/160028.html
標籤:其他
上一篇:云上應用安全
下一篇:主從 分庫 MySQL
