不停机配置 MySQL 主从

最近工作中遇到一个需求:希望不停机的情况下配置第一台 MySQL Slave 服务器。因为搜不到有效的资料,记录下我的实现方式。

前置条件

MySQL 数据目录硬盘需要有快照的能力,例如云服务器的快照功能,可以保证数据目录有效。

Slave 服务器设置主服务器的命令

CHANGE MASTER TO MASTER_HOST = '10.*.*.36',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'replpassword',
MASTER_PORT = 3306,
MASTER_LOG_FILE = 'binlog.000554',
MASTER_LOG_POS = 23541342; 

疑难点:如果 MySQL 未启动,怎么看当前的 MASTER_LOG_POS 是多少? 如果已经开启 GTID,可以直接通过 MASTER_AUTO_POSITION 这个选项来自动同步;默认未开启,所以需要知道快照时刻的 MASTER_LOG_POS

配置步骤

  1. 通过快照功能生成云硬盘,将该硬盘挂载到 Slave 服务器;不支持直接挂载的话也可以 scp 到目标服务器。

  2. 禁止启动数据库避免 binlog 被更新。对最新的 binlog 文件使用 mysqlbinlog -d db_name binlog.000551 | grep end_log_pos 导出最后一条 position 位置,这样就已经获取到了 MASTER_LOG_POS 的数值。

    • 后来想到,你也可以考虑 mysqlbinlog 的 --start-datetime 选项设置接近快照的时间(未测试)
    • mysqlbinlog 命令可通过 mysql-server-core-8.0 安装,无需启动 MySQL 即可读取 binlog 日志
  3. 修改 server_uuid,位于数据目录下的 auto.cnf 中,否则会提示

    Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.

    uuid 生成方式:select uuid();

  4. 修改 server-id,位于 my.cnf 中,否则会提示

    Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; these ids must be different for replication to work (or the --replicate-same-server-id option must be used on slave but this does not always make sense; please check the manual before using it).

  5. 启动 slave,按以上 SQL 配置 master

    • start slave
    • show slave status;,当 Slave_IO_RunningSlave_SQL_Running 都是 Yes 说明配置成功了。

如何观察 Slave 是否大幅度落后于 master?

  1. 为 master 创建一张表 t,只有一个字段 t, 类型为 datetime,插入当前的时间。
  2. 设置定时器每隔几秒 UPDATE t SET t = NOW(); 观察 Slave 表的 t 是否为最新时间。

举一反三:如何零宕机迁移数据库?

可以通过此方法配置好 Slave,并在约定的时间点将 Slave 切成 Master,锁定原服务器的同时把新服务器设定为数据源。

文章评论:做一头严肃的大叫驴

根据过去的经验得出,大多数评论是毫无意义的灌水,还有一小部分内容是针对文章的补充和纠错。如果你有建议请邮件联系,我将视反馈的重要程度和自己当月的经济水平发红包奖励。当然,也不一定会回复,这取决于邮件的内容质量。

我的团队正在招人

如果你是开发、运维、视觉/UI/UED设计师、产品经理,想成为我的同事可投递简历,邮箱 daijie@php.net