Cheug's Blog

当前位置:网站首页 / SQL / 正文

mysql基于 Binlog 的主从复制平滑迁移

2026-02-24 / SQL / 9 次围观 / 0 次吐槽 /

第一步:配置旧库(主库)

旧库必须开启了 binlog(二进制日志),这是同步数据的基石。

    1.检查旧库配置 (/etc/mysql/my.cnf/etc/mysql/mysql.conf.d/mysqld.cnf),确保有以下参数:

[mysqld]server-id = 1
log_bin = /var/log/mysql/mysql-bin.log

(如果修改了配置,需要重启旧库。如果已经开启了,则跳过重启)

    2.在旧库上创建一个专门用于同步的账号:

CREATE USER 'repl_user'@'%' IDENTIFIED BY '你的同步密码';GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
FLUSH PRIVILEGES;

第二步:获取旧库的“快照”和“位点”(关键)

我们需要导出一份旧库的当前数据,并且记住导出这一瞬间,日志走到了哪个位置。

    1.在旧库服务器上执行(替换密码和库名):

# --single-transaction 保证导出时不锁表(不影响业务写入)
# --master-data=2 会在导出的 SQL 文件里自动记录当时的 Binlog 文件名和位置
mysqldump -u root -p \
  --single-transaction \
  --master-data=2 \
  --routines --events --triggers \
  --databases sql1 sql2 > /tmp/snapshot.sql

导出完成后,打开 head -n 30 /tmp/snapshot.sql | grep "CHANGE MASTER TO",记下这两个值:

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000022', MASTER_LOG_POS=175710;

  2.导出指定用户的权限文件

# 请将 IN (...) 括号里的用户名替换为你真正需要迁移的两个用户名
mysql -u root -p -B -N -e \
"SELECT CONCAT('SHOW CREATE USER \'', user, '\'@\'', host, '\'; SHOW GRANTS FOR \'', user, '\'@\'', host, '\';') FROM mysql.user WHERE user IN ('user1', 'user2');" \
| mysql -u root -p -B -N \
| sed 's/$/;/g' > /tmp/users.sql


第三步:配置新库并导入数据

    1.配置新库,确保新库的 server-id 和旧库不一样(比如设为 2) (/etc/mysql/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.cnf)

[mysqld]
server-id = 2
log_bin = /var/log/mysql/mysql-bin.log

#持久化
replicate-do-db = sql1
replicate-do-db = sql2

    2.重启新库生效。

    3.把刚才旧库导出的用户权限文件和数据导入到新库:

mysql -u root -p < /tmp/users.sql

# 强制刷新权限,让账号立刻生效
# mysql -u root -p -e "FLUSH PRIVILEGES;"

mysql -u root -p < /tmp/snapshot.sql

第四步:开启同步,让新库同步旧库数据

    1.设置只同步指定的数据库

-- 设置同步白名单(只同步这两个库,如果有其他库请继续用逗号隔开)
CHANGE REPLICATION FILTER REPLICATE_DO_DB = (sql1, sql2);

    2.登录到新库的 MySQL 命令行,告诉它旧库在哪里,以及从哪个位置开始同步:

CHANGE MASTER TO
  MASTER_HOST='旧库的IP地址',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='你的同步密码',
  MASTER_LOG_FILE='刚才记下的文件名',  -- 例如 'mysql-bin.000022'
  MASTER_LOG_POS=刚才记下的数字;      -- 例如 175710;

    3.开始同步

START SLAVE;

    4.检查同步状态:

SHOW SLAVE STATUS \G


如果 Slave_IO_RunningSlave_SQL_Running 都是 Yes,说明同步成功了! 看 Seconds_Behind_Master 这个值,等它变成 0,就说明新库已经和旧库完全实时同步了。

第五步:业务切换(割接)

  1. 停旧库写入:把旧库设为只读 SET GLOBAL read_only = 1;,或者直接把应用服务停掉。

  2. 确认完全同步:在新库上最后看一眼 SHOW SLAVE STATUS \G;,确保 Seconds_Behind_Master 为 0。

  3. 新库解除主从关系:在新库执行 STOP SLAVE; RESET SLAVE ALL;,让新库变成独立的主库。

  4. 修改代码配置:把你的业务代码里的数据库 IP 改为新库 IP

  5. 启动业务:大功告成,迁移过程对用户基本无感(只断开几秒钟)。



Powered By Cheug's Blog

Copyright Cheug Rights Reserved.