MySQL主从虚拟机配置的核心思路是:通过虚拟机快照或克隆快速复制出两台相同环境的主机,再借助binlog和GTID实现数据同步;故障排查则从IO线程与SQL线程的状态入手,结合SHOW SLAVE STATUS的报错字段逐层定位。
虚拟机环境里搭建MySQL主从要注意什么
用虚拟机做MySQL主从实验,最大的好处是快照回滚方便,尤其适合反复练习配置步骤,但虚拟机也有几个坑,提前避开能省不少排查时间。
硬件资源分配:主从至少各分配2核CPU+2GB内存,磁盘用SSD,如果机器配置低,建议关掉MySQL的innodb_buffer_pool_size默认值,直接设成256MB,避免内存交换引发同步中断。
网络模式选择:虚拟机网络务必选桥接模式,不要用NAT,NAT模式下你很难在主库上把从库IP加进授权白名单,而桥接模式下两个虚拟机IP在同一网段,互相ping通就简单多了。
操作系统与MySQL版本:主从两端尽量使用完全相同的MySQL版本,比如都是8.0.36,跨大版本(5.7到8.0)虽然兼容,但密码插件和字符集规则不同,会导致复制中断,行业共识认为,小版本差异影响不大,但大版本统一更稳妥。
克隆后的初始化处理:如果你用克隆功能复制虚拟机,克隆出来的实例会带着原机器的server-uuid,这会让主从识别错乱,克隆后必须修改/var/lib/mysql/auto.cnf里的UUID,或者直接删除该文件重启MySQL。
从零配置MySQL主从复制:虚拟机组网实操步骤
假设你已经准备好两台虚拟机,分别叫vm-master和vm-slave,系统是CentOS 7或Ubuntu 22.04,MySQL版本8.0,下面按顺序操作。
配置主库(vm-master)
编辑/etc/my.cnf(Ubuntu是/etc/mysql/mysql.conf.d/mysqld.cnf),在[mysqld]段下加入:
server-id=1 log-bin=mysql-bin binlog-format=ROW gtid_mode=ON enforce_gtid_consistency=ON
这里用GTID模式替代传统的binlog+日志位置点,原因很简单:GTID自动定位同步位置,故障后从库重连不需要手动指定MASTER_LOG_FILE和MASTER_LOG_POS,MySQL 8.0默认推荐这种方式。
重启主库:
systemctl restart mysqld
登录MySQL创建复制账号:
CREATE USER 'repl'@'%' IDENTIFIED BY '复制的强密码'; GRANT REPLICATION SLAVE ON . TO 'repl'@'%'; FLUSH PRIVILEGES;

注意:从库连接时使用的IP,就是你要在授权里写的范围,如果从库IP会变,直接用'repl'@'%',只在虚拟机实验环境里这样做,生产环境千万别学。
配置从库(vm-slave)
同样编辑my.cnf,设置:
server-id=2 relay-log=relay-bin read_only=ON gtid_mode=ON enforce_gtid_consistency=ON
read_only=ON防止业务直接写从库,但要注意它不阻止super权限用户写入。
重启从库后,进入MySQL执行:
CHANGE MASTER TO MASTER_HOST='192.168.1.10', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='复制的强密码', MASTER_AUTO_POSITION=1; START SLAVE;
检查状态:
SHOW SLAVE STATUSG
看到Slave_IO_Running: Yes和Slave_SQL_Running: Yes就算成功。
验证配置是否生效
在主库建一个测试库和表:
CREATE DATABASE testdb; USE testdb; CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(50)); INSERT INTO t1 VALUES (1,'hello');
然后去从库执行SELECT FROM testdb.t1;,能查到数据说明同步链路通了。
主从同步故障排查:从现象到根因
虚拟机环境下的主从故障,80%以上集中在IO线程无法连接和SQL线程执行报错,下面按现象拆解。
IO线程显示Connecting且久连不上
这是最常见的报错,原因通常是三个方向:
- 网络不通:先
ping MASTER_HOST,再看telnet 主库IP 3306,虚拟机防火墙容易漏放3306端口,执行firewall-cmd --add-port=3306/tcp --permanent再重载。 - 授权问题:报错
Access denied for user 'repl',说明授权语句没生效,重新执行GRANT后用SELECT user,host FROM mysql.user;确认。 - 端口监听异常:主库
netstat -anp | grep 3306只显示0.0.1,说明bind-address没放开,在my.cnf里改为bind-address=0.0.0.0。
排查时最实用的命令是:
SHOW SLAVE STATUSG
看Last_IO_Error字段,多数情况它会直接告诉你具体原因,比如error connecting to master 'repl@192.168.1.10:3306' - retry-time: 60 retries: 1,照这个方向查,基本能解决。
SQL线程停止或报错
如果Slave_IO_Running: Yes

但Slave_SQL_Running: No,说明IO线程拿到了binlog,但执行线程卡住了,常见原因有两种:
主从数据不一致:在主库执行了从库已知表中不存在的行删除,或者从库表结构被改动,解决方式:
STOP SLAVE; SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;
但这是临时跳过,只适合跳过确实无影响的语句,更稳妥的做法是找到报错语句,手动在从库补齐数据,再START SLAVE。
GTID事务冲突:GTID模式下,从库已经执行过某个事务,又收到同一GTID的事务,会报Duplicate entry,这种情况不能用sql_slave_skip_counter,需要:
STOP SLAVE; RESET MASTER; -- 只在从库上,相当于清空自身GTID CHANGE MASTER TO MASTER_AUTO_POSITION=1; START SLAVE;
注意RESET MASTER会清空从库二进制日志,如果你的从库下面还有下级从库,这个方法不可用。
主从延迟持续增长
延迟是虚拟机上最容易出现的问题,因为IO性能有限,现象是Seconds_Behind_Master从几秒涨到几百秒。
原因分析:
- 从库
relay log写入慢,常见于磁盘IO瓶颈 - 主库写入并发高,但从库是单线程的SQL_THREAD(除非开启并行复制)
- 网络带宽不足,binlog同步耗时
解决思路:
- 在从库开启并行复制(MySQL 8.0默认已启用,但需要调
slave_parallel_workers大于0) - 主库binlog设置为
ROW格式,日志变大,可改用MIXED,减少网络传输 - 如果延迟持续,把从库的
innodb_flush_log_at_trx_commit设为2(不要设为0),降低磁盘同步频率
业内专家指出,大多数虚拟机的延迟问题都出在磁盘读写速度上,优先排查iostat的%util数值。
虚拟机场景下的常见误区
很多人在虚拟机里配置主从,失败后反复折腾配置文件,其实问题往往出在初始状态不干净。
- 从库已经有业务数据,直接
CHANGE MASTER会导致主键冲突 - 主从的
server_id都设置了1,导致互相识别错误 - 从库没有开启
relay_log,MySQL虽然会默认生成,但命名不统一影响管理
规避方法是:配置前先做一次从库全量重建,具体操作:
mysqldump -uroot -p --single-transaction --source-data=2 --all-databases > backup.sql

在从库执行导入前,先STOP SLAVE并RESET SLAVE ALL,导入完再重新CHANGE MASTER,这样能避开大多数历史脏数据问题。
Q&A:mysql主从虚拟机配置与故障排查常见问题
主从虚拟机里配置完成后,三天后突然中断,Slave_IO_Running变成No,怎么处理?
先看Last_IO_Error,常见原因是虚拟机的IP因DHCP租约过期而改变,用桥接模式时,建议在宿主机路由器上给虚拟机绑定静态IP,或者在虚拟机里手动配置/etc/sysconfig/network-scripts/ifcfg-(CentOS)或netplan(Ubuntu),IP固定后,重新执行CHANGE MASTER TO MASTER_HOST='固定IP',再START SLAVE,如果错误信息包含Got fatal error 1236,说明主库binlog已经被清掉或被我们删除,此时需要重新做主从:主库FLUSH LOGS获取当前binlog位置,或者直接重建从库,在测试环境用后者最省事。
从库因为磁盘满而停止复制,清理空间后如何恢复?
直接执行START SLAVE通常就能恢复,MySQL会把SQL线程跑到的位置持久化在relay-log.info文件里,清理空间后两个线程会自动继续,如果START SLAVE后仍然报错,检查Slave_SQL_Running_State,大概率是磁盘空间不足导致中继日志写入不完整,此时需要STOP SLAVE,清空relay-log目录下残留的文件,再START SLAVE,注意不要删掉relay-log.info,否则就得用CHANGE MASTER重新指定同步点。
在虚拟机克隆出来的从库上配置主从,为什么总是报server_uuid重复?
这是克隆虚拟机最常见的坑,MySQL 8.0的server_uuid存储在/var/lib/mysql/auto.cnf中,克隆后该文件内容与主库一致,从库启动时会用这个UUID去注册,主库发现两个相同UUID的实例,会拒绝后者连接,解决方法是登录从库MySQL执行SHOW VARIABLES LIKE 'server_uuid';确认当前值,然后停止数据库,删除auto.cnf文件,重启数据库后自动生成新UUID,再重新配置主从即可。
主从虚拟机配置的成败,往往不在SQL语句本身,而在于网络、UUID、权限这些"环境细节",固定好IP、克隆后清理UUID、用GTID模式,这套组合在虚拟机上跑通后,生产环境的物理机部署也只是换个IP和端口而已,遇到报错先看SHOW SLAVE STATUS的Last_IO_Error和Last_SQL_Error,按字段内容去处理,远比盲目改配置文件高效。