我正在尝试在 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_Running
是No
,并且在启动它 ( 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
谷歌搜索建议我需要使用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
文件如下:注意:
server_id = 2
在复制从站上。另请注意,如果没有该
relay-log
选项,该命令SHOW MASTER STATUS;
不会在主数据库容器上返回任何结果。还有一个可能的未决问题,默认情况下,当您使用
docker stop
它时,它会要求容器终止(通过向 docker entrypoint 命令发送 SIGHUP ),如果它没有在 10 秒内终止,则会被强制停止。我需要确保有足够的时间来关闭它,因为在负载下可能需要一段时间才能自行解决,结果可能导致数据丢失。