type
status
date
slug
summary
tags
category
icon
password
背景
建立半同步複製
必須滿足的條件
- 安裝 pluging 需要支援 dynamic loading 的 MySQL Server,透過以下方式確認:
- 已配置 Replication。
- 不可以配置多個 replication channel,semi-sync 只支援默認 channel。
安裝 semi-sync plugin
開啟 semi-sync
必須在 Source 和 Replica 都同時啟用 plugin 設定才能生效,並且需要重啟 IO_THREAD
配置
rpl_semi_sync_source_timeout
:控制 source 等待 replica 的 timeout 時間,如果超過此時間會變回異步複製。以毫秒為單位,預設值為 10000 (10秒)。
rpl_semi_sync_source_wait_for_replica_count
:控制 source 需要等待多少 replica 返回 ACK,默認值為 1 表示僅需等待至少一個 replica 確認接收到 transaction。
rpl_semi_sync_source_wait_point
:- AFTER_SYNC:source 將 transaction 寫入 binlog 和 replica,並將 binlog sync 到 disk,之後 source 等待 replica 的 ack 回覆後,收到之後會將 transaction commit 給 store engine 並將結果返回給 client 端。
- source 將 transaction 寫入 binlog
- source 將 binlog sync 到 disk。
- 等待 replica 的 ack 回覆。
- soure 將 transaction commit 到 store engine,並將結果返回 client 端。
- AFTER_COMMIT:
測試
正常關閉 Source
- 暫停 replica 模擬 replica 尚未返回 ACK
- source 執行 DML 語句
可以看到因為沒有 replica 返回 ACK 確認收到 transaction,因此沒有順利 commit
- 正常方式安全關閉 Source
- 關閉期間會發現 insert 語句會被 commit
結果:
- 對於程式端來說
name='test3'
的數據已經成功寫入 DB 內,但是 Replica 還沒收到該筆資料,因此如果這時候將 Replica 切換成 Source,將會導致丟失此筆資料。
- 如果這時候不進行 HA,而是將 Source 復原,並恢復 Replication,則不會發生任何問題。
強制關閉 Source
- 暫停 replica 模擬 replica 尚未返回 ACK
- source 執行 DML 語句
可以看到因為沒有 replica 返回 ACK 確認收到 transaction,因此沒有順利 commit
- 強制關閉 Source
- 可以看到原本的語句會直接返回 lost connection 的錯誤
結果:
- 對於程式端來說
name='test4'
的數據沒有成功寫入 DB 內,因此如果這時候將 Replica 切換成 Source,不會導致數據丟失的問題。
- 如果這時候不進行 HA,而是將 Source 復原並恢復 Replication,
- 1
- relay log
- 會讓
name='test4'
會正常寫入,導致和程式端得到的結果有認知不同的問題。
結論
此問題有在 MySQL Bug Report 看到有人回報,官方回覆此行為符合他們的預期,官方會將此狀況列為文檔說明缺失會進行修正:
With semisynchronous replication, if the source crashes and a failover to a replica is carried out, the failed source should not be reused as the replication source, and should be discarded. It could have transactions that were not acknowledged by any replica, which were therefore not committed before the failover.
If your goal is to implement a fault-tolerant replication topology where all the servers receive the same transactions in the same order, and a server that crashes can rejoin the group and be brought up to date automatically, you can use Group Replication to achieve this. For information, see Chapter 18, Group Replication.
上述說明中提到如果 Source crash 掉後可能有 Replica 不知道的 Transaction,因此應該直接丟棄不該繼續使用。