Replication

使用 percona 和 docker 的 MySQL 複製從站

  • June 12, 2019

我正在嘗試在 docker 容器中執行 MySQL 複製從屬。我們在生產環境中執行 MySQL 5.7.24-27-log,它來自 percona 儲存庫(Ubuntu 18.04)。

我曾經xtrabackup備份、準備和發送一個用於複製的起始數據集,然後我docker pull percona像這樣啟動了 percona docker 映像():

$ docker run --name mysql-replication -v /replication/data:/var/lib/mysql -v /replication/docker.cnf:/etc/mysql/docker.cnf:ro -e MYSQL_ROOT_PASSWORD=xxxx -P -d percona

我的 docker.cnf 只記錄了伺服器 ID(我從percona圖像中複製了它)。

[mysqld]
skip-host-cache
skip-name-resolve
bind-address    = 0.0.0.0
server-id       = 4

然後使用CHANGE MASTER等。我的複制執行得很好。

我的意圖(根據卷掛載-v /replication/data:/var/lib/mysql)是將所有 MySQL 數據保留在主機上,並將複製 docker 容器視為臨時的,即容器中沒有狀態。server-id如果我需要通過停止現有容器、將數據複製到別處、更改並執行新容器來啟動另一個複制容器,也應該很容易。

為了測試這一點,在它設置並正常執行後(我看了Seconds_Behind_Master下拉菜單0),我想我應該能夠刪除容器並重新創建它,並且複制仍然可以正常工作。因此我嘗試了這個:

$ docker stop mysql-replication
$ docker rm mysql-replication
$ docker run ... // same command as before

當我這樣做並連接到在容器中執行的 MySQL 時,我發現它Slave_IO_RunningNo,並且在啟動它 ( START SLAVE;) 後,我得到以下資訊(如中所示SHOW SLAVE STATUS;):

Last_Error: Could not execute Update_rows event on table databasename.tablename; Can't find record in 'tablename', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-bin.000681, end_log_pos 9952

databasename並且tablename是真實的數據庫和表名)

起初我以為我可能搞砸了,但我現在已經嘗試了很多次來嘗試解決問題。使用docker diff mysql-replication顯示對正在執行的容器沒有任何變化,這似乎很重要:

$ docker diff mysql-replication 
C /run
C /run/mysqld
A /run/mysqld/mysqld.pid
C /var
C /var/log
A /var/log/mysql

Google搜尋建議我需要使用RESET SLAVE;START SLAVE;但這似乎無法解決它 - 就像數據(容器外部)不再與主伺服器同步,因此複製無法繼續。

任何人都可以在我正在做的事情中找出漏洞嗎?

非常感謝。

此問題的根本原因是文件中缺少該relay-log選項mysql.cnf(或者在這種情況下,由於 docker 卷掛載,該docker.cnf文件)。這會導致文件的創建和使用,例如89726507f176-relay-bin.000002最初,89726507f176機器的主機名在哪裡(在創建映像時由 docker 守護程序隨機分配)。當容器停止、刪除和重新創建時,會創建和使用一組新文件(例如be0c801d95bc-relay-bin.000407),但這會導致同步問題。

relay-log通過在文件中明確指定一個值,docker.cnf可以毫無問題地刪除和重新創建容器。

作為旁注,我還建議 /var/log/mysql 目錄沒有被掛載存在問題 - 事實並非如此。但是,如果您指定了一個值,log_bin = /var/log/mysql/mysql-bin.log例如,那麼這是一個要求。如果您不指定此路徑,則二進制日誌似乎儲存在本地 /var/lib/mysql 中,該 /var/lib/mysql 已安裝在容器外部。

我的最終docker.cnf文件如下:

[mysqld]
skip-host-cache
skip-name-resolve
bind-address        = 0.0.0.0

binlog-ignore-db = mysql
replicate-ignore-db = mysql

log_bin = /var/log/mysql/mysql-bin.log

relay-log   = replication-1
server_id   = 1

注意:server_id = 2在複製從站上。

另請注意,如果沒有該relay-log選項,該命令SHOW MASTER STATUS;不會在主數據庫容器上返回任何結果。

還有一個可能的未決問題,預設情況下,當您使用docker stop它時,它會要求容器終止(通過向 docker entrypoint 命令發送 SIGHUP),如果它沒有在 10 秒內終止,則會被強制停止。我需要確保有足夠的時間來關閉它,因為在負載下可能需要一段時間才能自行解決,結果可能導致數據失去。

引用自:https://dba.stackexchange.com/questions/239639