MySQL 8.0 主从同步 & 双主配置
环境说明
| 角色 | IP |
|---|---|
| Master(主) | 192.168.0.1 |
| Slave(从) | 192.168.0.2 |
双主模式下两台互为主从,192.168.0.1 和 192.168.0.2 均需配置。
一、主从同步
1. 主库配置(192.168.0.1)
编辑 /etc/my.cnf:
[mysqld]
server-id = 1
log_bin = mysql-bin
binlog_format = ROW
binlog_do_db = your_database # 可选,指定同步的库,不写则同步全部
expire_logs_days = 7
重启 MySQL:
systemctl restart mysqld
创建复制账号(使用 mysql_native_password):
CREATE USER 'repl'@'192.168.0.2'
IDENTIFIED WITH mysql_native_password BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.2';
FLUSH PRIVILEGES;
查看主库 binlog 状态,记录 File 和 Position:
SHOW MASTER STATUS;
+------------------+----------+
| File | Position |
+------------------+----------+
| mysql-bin.000001 | 157 |
+------------------+----------+
2. 从库配置(192.168.0.2)
编辑 /etc/my.cnf:
[mysqld]
server-id = 2
relay_log = relay-bin
read_only = 1
重启 MySQL:
systemctl restart mysqld
配置同步并启动:
CHANGE MASTER TO
MASTER_HOST = '192.168.0.1',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_LOG_FILE = 'mysql-bin.000001', -- 替换为主库 SHOW MASTER STATUS 的值
MASTER_LOG_POS = 157, -- 替换为主库 SHOW MASTER STATUS 的值
GET_MASTER_PUBLIC_KEY = 1;
START SLAVE;
验证同步状态:
SHOW SLAVE STATUSG
关键字段正常值:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Seconds_Behind_Master: 0
主库执行脚本(master_setup.sh)
#!/bin/bash
# 在 192.168.0.1 上执行
MYSQL_USER="root"
MYSQL_PASS="your_root_password"
mysql -u$MYSQL_USER -p$MYSQL_PASS <<EOF
CREATE USER 'repl'@'192.168.0.2'
IDENTIFIED WITH mysql_native_password BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.2';
FLUSH PRIVILEGES;
SHOW MASTER STATUS;
EOF
从库执行脚本(slave_setup.sh)
执行前先将脚本中的
MASTER_LOG_FILE和MASTER_LOG_POS替换为主库SHOW MASTER STATUS的实际值。
#!/bin/bash
# 在 192.168.0.2 上执行
MYSQL_USER="root"
MYSQL_PASS="your_root_password"
MASTER_LOG_FILE="mysql-bin.000001" # 替换
MASTER_LOG_POS=157 # 替换
mysql -u$MYSQL_USER -p$MYSQL_PASS <<EOF
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST = '192.168.0.1',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_LOG_FILE = '$MASTER_LOG_FILE',
MASTER_LOG_POS = $MASTER_LOG_POS,
GET_MASTER_PUBLIC_KEY = 1;
START SLAVE;
SHOW SLAVE STATUSG
EOF
二、双主同步
双主在主从基础上,让 192.168.0.2 也作为主库,192.168.0.1 同时作为从库。
1. 192.168.0.2 补充配置
编辑 /etc/my.cnf,在原有配置基础上增加:
[mysqld]
server-id = 2
log_bin = mysql-bin
binlog_format = ROW
relay_log = relay-bin
read_only = 0 # 双主模式去掉只读
auto_increment_increment = 2 # 防止主键冲突
auto_increment_offset = 2 # 192.168.0.2 从偶数开始
192.168.0.1 同步增加:
auto_increment_increment = 2
auto_increment_offset = 1 # 192.168.0.1 从奇数开始
auto_increment错开是防止双主同时写入时主键冲突的关键配置。
重启两台 MySQL:
systemctl restart mysqld
2. 在 192.168.0.2 上创建复制账号
CREATE USER 'repl'@'192.168.0.1'
IDENTIFIED WITH mysql_native_password BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.1';
FLUSH PRIVILEGES;
SHOW MASTER STATUS;
3. 在 192.168.0.1 上配置指向 192.168.0.2 的同步
CHANGE MASTER TO
MASTER_HOST = '192.168.0.2',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_LOG_FILE = 'mysql-bin.000001', -- 替换为 192.168.0.2 的值
MASTER_LOG_POS = 157, -- 替换为 192.168.0.2 的值
GET_MASTER_PUBLIC_KEY = 1;
START SLAVE;
SHOW SLAVE STATUSG
双主执行脚本
node2_master_setup.sh(在 192.168.0.2 上执行):
#!/bin/bash
# 在 192.168.0.2 上执行,创建供 192.168.0.1 使用的复制账号
MYSQL_USER="root"
MYSQL_PASS="your_root_password"
mysql -u$MYSQL_USER -p$MYSQL_PASS <<EOF
CREATE USER 'repl'@'192.168.0.1'
IDENTIFIED WITH mysql_native_password BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.1';
FLUSH PRIVILEGES;
SHOW MASTER STATUS;
EOF
node1_slave_setup.sh(在 192.168.0.1 上执行):
#!/bin/bash
# 在 192.168.0.1 上执行,指向 192.168.0.2 作为主库
MYSQL_USER="root"
MYSQL_PASS="your_root_password"
MASTER_LOG_FILE="mysql-bin.000001" # 替换为 192.168.0.2 SHOW MASTER STATUS 的值
MASTER_LOG_POS=157 # 替换
mysql -u$MYSQL_USER -p$MYSQL_PASS <<EOF
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST = '192.168.0.2',
MASTER_USER = 'repl',
MASTER_PASSWORD = 'Repl@123456',
MASTER_LOG_FILE = '$MASTER_LOG_FILE',
MASTER_LOG_POS = $MASTER_LOG_POS,
GET_MASTER_PUBLIC_KEY = 1;
START SLAVE;
SHOW SLAVE STATUSG
EOF
三、常见问题
Q:Slave_IO_Running: No
检查主库防火墙是否放开 3306,以及复制账号的 host 是否匹配。
Q:主键冲突
双主模式必须配置 auto_increment_increment 和 auto_increment_offset,两节点的 offset 不能相同。
Q:GTID 模式
MySQL 8.0 推荐使用 GTID 替代传统 binlog position 方式,更不容易出错,后续可升级配置。