news 2026/9/28 22:54:51

MySQL主从复制实战:GTID、binlog配置与故障排查指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL主从复制实战:GTID、binlog配置与故障排查指南

搞主从配置的文档满网都是,但大多数都是“照官方文档抄一遍,能通就行”的水平。我今天写这篇,不是又给你贴一遍CHANGE MASTER TO,而是想把我实际在生产环境折腾MySQL主从的经验、踩过的坑、还有怎么排查的思路一次性整理出来。尤其是很多教程忽略的:binlog格式怎么选、GTID和文件位置复制哪种靠谱、复制中断后怎么优雅恢复、以及“只同步某几张表”这种实际到不能再实际的需求。

如果你是刚接触MySQL的运维新手,或者被主从复制搞得焦头烂额的开发,这篇应该能帮你少走不少弯路。我会按我的实际配置顺序来写,你照着一步步来,大概率能一次配通。

1. 先搞懂主从复制的核心逻辑,别急着敲命令

很多人一上来就改配置文件,结果出问题了不知道从哪排查。我建议先花两分钟理解主从到底在干什么,这对后面解决问题帮助极大。

1.1 主从复制的本质:一个“日志搬运工”的流水线

主从复制可以通俗地理解为一条流水线:主库(Master)把所有写操作记录到自己的二进制日志(binlog)里,从库(Slave)通过网络把主库的binlog拉到本地,写入自己的中继日志(relay log),然后从库再把这些日志在本地“重放”一遍,得到和主库一致的数据。

这个过程中有三个关键线程在干活:

  • 主库上的Binlog Dump线程:负责把binlog发送给从库。
  • 从库上的I/O线程:负责接收主库发来的binlog,并写入本地的relay log。
  • 从库上的SQL线程:负责读取relay log,并在从库上执行。

理解了这个模型,你就明白为什么从库会出现延迟,也明白为什么主库挂了从库还能继续(因为relay log可能还没应用完)。这套机制是2000年左右就定型的架构,到今天依然是MySQL高可用的基石,不管是传统的文件位置复制,还是后面讲的GTID复制,本质都没有跳出这个框架。

1.2 两种复制方式:二进制日志位置 vs GTID,我推荐你用GTID

传统的复制方式是“基于二进制日志位置”,从库需要告诉主库:“我从这个文件的这个偏移量开始拉日志”。这种方式最大的缺点是,如果从库的中继日志丢了或主库的binlog被清理了,你很难精确找到断点。而且Failover(故障切换)的时候,去找“位置”是一件非常痛苦的事情。

MySQL 5.6开始引入GTID(全局事务标识),5.7、8.0已经非常成熟。GTID给每个事务分配了一个全局唯一的ID,格式是服务器UUID:事务序号。从库不需要关心从哪个文件的哪个位置开始,只需要说“我已经执行到事务3E11FA47-71CA-11E1-9E33-C80AA9429562:10,你从这个后面继续给我发就行”。这就像你看连续剧,不需要记住看到第几集的第几分钟,只需要记住“我看到第几集了”,就能无缝续播。

强烈建议:新搭的主从一律用GTID方式。配置里加两个参数就行,后面我会提到。

2. 环境准备:我的主从密码和账号规划

在动手之前,先把环境说清楚。我这边生产环境是两台Linux服务器,CentOS 7.9,MySQL版本是8.0.32(通过二进制包部署,没用系统自带的yum源)。Windows上的玩法我后面也会提一句,因为不少开发同学的测试机是Windows。

角色IPserver-idMySQL版本
Master192.168.1.1018.0.32
Slave192.168.1.1128.0.32

这里有个很容易踩坑的点:server-id 必须不同,而且不能为0。如果两台机器的server-id一样,从库会报主键冲突一样的错误,日志里会出现Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs。实战中不少人把两台机器克隆了,MySQL安装路径也一样,就连server-id也顺手复制了,结果折腾半天连不上。

2.1 从零装好一套MySQL 8(Linux环境实例)

因为我是用二进制包方式安装的,这里简单记录一下关键步骤,装过的可以直接跳过:

# 下载解压(版本号按你自己的来) cd /usr/local/ wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz tar -xvf mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz mv mysql-8.0.32-linux-glibc2.12-x86_64 mysql # 创建mysql用户和目录 useradd -s /sbin/nologin mysql mkdir -p /data/mysql chown -R mysql:mysql /data/mysql /usr/local/mysql # 初始化数据目录(这一步密码是随机生成的,在日志里) /usr/local/mysql/bin/mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql

用--initialize-insecure的好处是root初始密码为空,登录后直接改就行,省得去日志里翻随机密码(我就是懒)。初始化完成后配置/etc/my.cnf,关键的几个参数我单独拎出来,下一节细说。配置好后注册systemd服务启动:

cat > /etc/systemd/system/mysqld.service << 'EOF' [Unit] Description=MySQL Server After=network.target [Service] Type=forking User=mysql Group=mysql ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf ExecStop=/usr/local/mysql/bin/mysqladmin -uroot -p shutdown Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable mysqld --now

顺便说一句Windows上装MySQL 8其实更简单,就去官网下个zip包,解压后自己建一个my.ini,以管理员身份打开命令行执行mysqld --initialize-insecure和mysqld --install,再net start mysql就能起来。Windows做从库和Linux做从库在配置上没有任何区别,只是binlog的路径写法要注意转义,比如log-bin="D:/mysql/logs/binlog",用正斜杠或者双反斜杠都行,别用单反斜杠。

2.2 准备一个专门用于复制的账号

登录主库,创建一个复制专用账号。我习惯用repl这个名字,一看就知道是干嘛的。不要用root账号去拉复制,这是大忌。

CREATE USER 'repl'@'192.168.1.%' IDENTIFIED BY 'StrongPass@2024'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.%'; FLUSH PRIVILEGES;

这个权限只需要REPLICATION SLAVE,不需要给其他权限。这里有个小坑:MySQL 8.0 默认的认证插件是caching_sha2_password,如果你的从库版本是5.7或者更早,可能连不上主库。解决方案是创建用户时指定mysql_native_password,但8.0.32之后的版本又逐步弃用了这个插件,建议直接用8.0对8.0,别混搭。如果非要混搭,从库连接时报错Authentication plugin 'caching_sha2_password' cannot be loaded,就得在主库上重新建用户或者改认证方式。

3. 主库和从库的my.cnf配置要点

配置文件是主从配置的灵魂。我直接把我线上用的配置贴出来,并逐条解释为什么这么写。

3.1 主库配置:binlog是命根子

[mysqld] server-id = 1 # 开启binlog,文件名前缀,建议带上主机名,方便区分 log-bin = /data/mysql/binlog/mysql-bin binlog_format = ROW # 高峰期binlog文件大小,默认128M,我习惯调成512M,减少文件轮转频率 max_binlog_size = 512M # binlog的过期时间,线上建议7天,测试环境可以设短一点 binlog_expire_logs_seconds = 604800 # 这个参数很重要,后面单表同步的时候会靠它 binlog_row_image = FULL # 这个决定了binlog的校验方式,分布式环境建议设NONE,否则有兼容性问题 binlog_checksum = NONE gtid_mode = ON enforce_gtid_consistency = ON

binlog_format = ROW是我特别要强调的。早期MySQL默认是STATEMENT,也就是记录SQL语句本身,主从执行同样的SQL。这在不确定函数(UUID、NOW())存在时会造成主从数据不一致。ROW格式记录的是“哪一行数据变成了什么”,虽然日志体积会大一些,但是最可靠。8.0里其实已经默认ROW了,但你要是从5.7老库升级来的,还是要确认一下。

binlog是主从复制的命根子,这句话一点不夸张。如果主库没开binlog,或者binlog被purge了,从库就断了根,只能重建。所以给binlog单独放一个目录是明智的,跟数据目录分开,避免磁盘满的时候互相挤兑。

binlog_checksum = NONE可能有人会问为什么不设CRC32。理论上是CRC32更安全,但我实际遇到过跨版本(5.7到8.0)复制时CRC校验不一致导致IO线程反复报错的案例,索性就统一用NONE了。如果你所有节点版本一致,保持CRC32问题也不大。

3.2 从库配置:一个参数避免误操作

[mysqld] server-id = 2 # 从库也建议开binlog,因为从库可能作为下一级主库(级联复制) log-bin = /data/mysql/binlog/mysql-bin binlog_format = ROW gtid_mode = ON enforce_gtid_consistency = ON log_slave_updates = ON # 从库设置为只读,防止客户端直接写入 read_only = ON # 即使是超级管理员也限制?这个参数看需求,开了就必须在这个库上执行super权限操作 # super_read_only = ON # relay log配置 relay_log = /data/mysql/relaylog/relay-bin # 防止SQL线程报错时无限重试,设置重试上限 slave_parallel_workers = 4 # 8.0默认的并行复制策略,0表示数据库级别并行,1表示日志级别并行 slave_parallel_type = LOGICAL_CLOCK

从库加read_only = ON是我强烈建议的。因为很多人测试的时候就顺手往从库插入数据,结果主从数据不一致,又找不到原因。开了read_only后,普通账号根本写不进数据,能拦住大部分手误。如果你用的是类似ProxySQL这类中间件,它也会自动识别read_only状态做读写分离,不会把写请求路由到从库。

slave_parallel_workers = 4和slave_parallel_type = LOGICAL_CLOCK是提升复制性能的关键。MySQL 8.0 默认已经是LOGICAL_CLOCK了,但如果你是从5.7升上来的,binlog里的信息可能不支持,建议升级后用mysqlbinlog验证一下,保证事务间并行不会出错。

3.3 记住这个检查命令:验证GTID配置是否生效

配置完成后,在主库执行:

SHOW VARIABLES LIKE 'gtid_mode'; SHOW VARIABLES LIKE 'enforce_gtid_consistency'; SELECT @@server_uuid;

如果两个变量都是ON,@@server_uuid输出一串UUID,那么配置就生效了。这一个UUID在后面的GTID复制中会反复出现。

4. 配置主从关系:从CHANGE MASTER到START SLAVE

配置好后,就要在从库上“告诉它主库在哪里”。这一步网上教程很多,但大部分都没讲清楚怎么处理GTID的问题。

4.1 先在主库上锁定数据,做一个一致性快照

在主库上执行:

FLUSH TABLES WITH READ LOCK;

这个命令的作用是把所有的表锁住,让主库暂时不能写数据。这时候在主库上执行:

mysqldump -uroot -p --all-databases --single-transaction --set-gtid-purged=ON --master-data=2 > /tmp/master_init.sql

注意,我们是锁了表之后才做的dump。--single-transaction对InnoDB保证的是一致性快照,可以不锁表,但这里是用了两个保险。--set-gtid-purged=ON会在dump文件中带上SET @@GLOBAL.GTID_PURGED='xxxx:1-100'这样的语句,告诉从库:“这些事务我已经有了,你不需要重复执行”。--master-data=2则会在文件里注释标注主库当前使用的binlog文件名和位置。

dump完成后记得UNLOCK TABLES,别锁着不放开,影响业务。

4.2 把快照导入从库

把/tmp/master_init.sql传到从库,然后:

mysql -uroot -p < /tmp/master_init.sql

这里有个坑,如果导入的备份文件里有GTID_PURGED相关语句,那么导入后从库的GTID状态已经是“追赶中”的状态了,不需要再额外指定MASTER_LOG_FILE和MASTER_LOG_POS。这是GTID复制比传统复制舒服的地方:不需要找binlog位置。

4.3 执行CHANGE MASTER TO

登录从库,执行:

RESET MASTER; -- 注意!这是从库,不是主库。可能有人误操作在主库执行了,那就完了。 CHANGE MASTER TO MASTER_HOST='192.168.1.10', MASTER_USER='repl', MASTER_PASSWORD='StrongPass@2024', MASTER_AUTO_POSITION=1, MASTER_CONNECT_RETRY=10, MASTER_HEARTBEAT_PERIOD=10; START SLAVE;

注意这里MASTER_AUTO_POSITION=1,就是GTID方式的关键。如果是传统方式,需要用MASTER_LOG_FILE='mysql-bin.000023', MASTER_LOG_POS=1567这样的形式,还要你手动去dump文件里查位置,麻烦不说还容易错。

关于RESET MASTER我特别提醒:这个命令会让从库的binlog和GTID状态清空。如果你是从库刚搭好、里面还没有业务数据,执行没问题。但如果你不小心在主库执行了,主库的binlog全都清空,所有从库都得重新做,这个事故我见过不止一次。执行前一定要SELECT @@server_id确认自己登的是从库。

4.4 验证主从状态:这两个值你必须会看

在从库上执行:

SHOW SLAVE STATUS\G

关注以下字段:

  • Slave_IO_Running: 必须是Yes。如果为Connecting,说明IO线程连不上主库,检查网络、账号密码。
  • Slave_SQL_Running: 必须是Yes。如果为No,说明SQL线程执行出错,通常是因为中继日志里的语句在从库执行时遇到冲突。
  • Seconds_Behind_Master: 主从延迟秒数。注意,这个值如果是NULL,说明SQL线程没运行,或者还没追上。
  • Last_IO_Error/Last_SQL_Error: 最近一次错误的详细信息,报错排查先看这里。

还有一个容易忽略的:Retrieved_Gtid_Set和Executed_Gtid_Set。这两个值分别表示从库拉取到哪了、执行到哪了。如果它们的差值越来越大,说明延迟在累积。

刚执行完START SLAVE后等几秒,看到Slave_IO_Running: Yes和Slave_SQL_Running: Yes,说明主从状态已经正常了。你可以到主库CREATE TABLE、INSERT数据,然后在从库查询验证。

5. 只同步一张表到本地?replicate-wild-do-table的正确打开方式

开头提到的热搜词里有“把远程库的这张表同步到本地”,这是很多人在做的数据抽取场景:不需要整个库同步,只要某几张核心表。这里要区分两种情况:一种是新搭建时只初始化那几张表,另一种是已有的从库上过滤复制。我建议用前者,因为后者有复制不一致的天然风险。

5.1 只dump需要的表

在主库准备数据时,用mysqldump指定表名:

mysqldump -uroot -p dbname table1 table2 --single-transaction --set-gtid-purged=ON > /tmp/partial_init.sql

这里如果表比较少,想直接连表结构都带上,加--no-data只导结构,再按条件导出数据。比如:

# 先导表结构 mysqldump -uroot -p dbname table1 --no-data > /tmp/partial_schema.sql # 再导最近一个月的数据 mysqldump -uroot -p dbname table1 --where="create_time > '2024-01-01'" --no-create-info >> /tmp/partial_data.sql

这部分数据导入从库后,从库上暂时是干净的状态。

5.2 在从库配置过滤规则

在从库的/etc/my.cnf中加入:

# 只同步db1库的table1和table2,其他忽略 replicate-wild-do-table = db1.table1 replicate-wild-do-table = db1.table2 replicate-wild-do-table = db1.table%

注意,这里支持通配符。但如果你用了通配符,实际上就把db1下的所有表都同步了。如果要精准同步某几张表,就写完整的表名。规则写完后必须重启MySQL,因为replicate-wild-do-table是静态参数,改完后要重启从库生效。

如果你需要把多个库的某些表同步过来,可以写多行。但一定要注意的是,replicate-wild-do-table和replicate-do-table这些过滤规则在GTID复制下有个坑:GTID会拉取主库的所有事务,但只在符合规则的表上执行,也就是说,拉到的事务仍然在relay log里,只是被SQL线程过滤掉了。这意味着如果你过度依赖过滤规则来减小同步数据量,relay log的磁盘占用反而可能变大了,因为IO线程还是把所有binlog都拉过来了。

5.3 一个更优方案:用binlog_row_image和binlog过滤来减少网络开销

前面配置里提到的binlog_row_image = FULL,这里再展开一下。ROW格式下,每行变更会记录“前镜像+后镜像”或者至少是“后镜像”。如果某些表有blob、text字段,一张行可能很大,日志量暴涨。有几种优化方式:

  • binlog_row_image = MINIMAL:只记录“唯一键字段 + 变更字段”,日志小很多,但可能在做回放时某些场景不稳定。如果只是同步几张小表,不用改。
  • 主库上binlog-do-db:只记录指定库的binlog,其他库不记录。这样可以减少从库IO线程的网络压力,但副作用是如果以后要扩展新的从库,那些被过滤掉的库没法搭了。

我个人的习惯是:如果明确知道要用在哪几个库,主库就配binlog-do-db = db1,从库再配replicate-wild-do-table,双重过滤。这是典型的“生产环境取交集”玩法,网络开销和磁盘开销都能压下来。

5.4 验证:主库写入,从库只看得到指定表

在主库执行:

USE db1; INSERT INTO table1 (id, name) VALUES (1, 'sync_test'); INSERT INTO table2 (id, name) VALUES (100, 'sync_test2'); USE testdb; INSERT INTO t (id, col) VALUES (999, 'this_should_not_sync');

等几秒后,在从库查询:

SHOW DATABASES; -- 应该只有db1和系统库,testdb不会出现 SELECT * FROM db1.table1; -- 应该有刚插入的那条数据 SELECT * FROM db1.table2; -- 应该有数据 USE testdb; -- ERROR 1049: Unknown database

注意,如果你主从之前的GTID已经同步到某一点,之后从库拉取了全部binlog,但过滤规则只对某些表执行,那么GTID_SET里还是会记录所有事务(过滤掉的事务同样会算作“已执行”)。这是GTID模式的一个特性,也是它“从库可用binlog做进一步分发”的基础。

6. 复制卡住、报错、延迟高的解决方法

主从配置好只是开始,日常维护才是大头。我最常遇到的是三类问题,这里直接给排查链路。

6.1 IO线程报错:Can't connect to MySQL server on '192.168.1.10' (111)

优先排查网络,然后看账号权限,最后看防火墙。111 拒绝连接,一般就是网络不通或者端口被屏蔽。用下面三条命令一次定位:

telnet 192.168.1.10 3306 ping 192.168.1.10 netstat -anp | grep 3306

如果是云服务器,阿里云/腾讯云的安全组也要放行3306,这是很多人忽略的。即使操作系统防火墙关了,安全组没加白名单照样连不上。账号权限可以通过GRANT REPLICATION SLAVE后记得FLUSH PRIVILEGES来验证。

6.2 SQL线程报错:Duplicate entry '1' for key 'PRIMARY'

这个错误太典型了:从库上已经有主键为1的数据,但主库又插入了一条主键为1的数据。或者反过来,从库自己写了一条数据,主库没这条数据,然后主库又执行了相同主键的插入,从库重放时冲突。

解决思路分三步:

  1. 先确定从库数据是不是“脏”了,看看本地自己写入了什么。如果从库数据不值得保留,停掉SQL线程然后跳过这个事务,最常用:
STOP SLAVE SQL_THREAD; SET GLOBAL sql_slave_skip_counter = 1; -- 传统复制用 START SLAVE SQL_THREAD;

但这在GTID模式下已经不可用了,MySQL 8.0 下需要用另一种方式(见下节)。

  1. 如果脏数据比较多,建议直接重建从库,不要慢慢跳事务,因为有的事务修改了多行,跳过会留下更多不一致的隐患。

  2. 如果偶尔一个事务就是需要跳过,GTID模式下可以用“注入空事务”的方式跳过。具体做法是找到报错事务的GTID,然后在从库手动执行一个空事务来弥补:

STOP SLAVE; SET GTID_NEXT='xxxx:12345'; -- 这里是报错的那个GTID BEGIN; COMMIT; SET GTID_NEXT='AUTOMATIC'; START SLAVE;

这种操作会让从库的GTID集合追上,但数据上可能还是缺了那个事务。只适合“明确该事务可忽略”的场景,不能滥用。

6.3 主从延迟高:Seconds_Behind_Master越来越大

出现延迟后先别急。检查几条:

  1. 从库CPU负载是否过高?有大查询正在跑会拖慢SQL线程。
  2. 主库是不是有大事务?比如DELETE FROM huge_table或ALTER TABLE,这类操作在从库上会同步放大(可能锁表、占IO)。
  3. 长事务会导致从库的relay log堆积。可以在从库上看:
SHOW PROCESSLIST;

如果一个线程的Info字段是System lock或者Waiting for table metadata lock,说明SQL线程被一个大操作卡住了。

还有一类隐蔽的场景:从库用的是机械盘或者单盘IOPS不足,而主库是SSD,这时候复制的瓶颈就在从库的磁盘。解决办法是把从库的redo log增大,比如innodb_redo_log_capacity = 8G(8.0.30后默认有该参数),让SQL线程在做checkpoint时没有那么频繁的fsync。另外innodb_buffer_pool_size也要给足,否则每一个变更都要读写磁盘,复制延迟会持续累积。

6.4 GTID复制下报错:The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs

这句话翻译成人话是:从库要求按GTID自动定位,但主库的binlog已经把从库需要的事务删掉了。通常发生在从库停机很久,或者主库的binlog过期时间设得太短。

遇到这个错误,没有别的办法,只能重建从库。不要想着“我就差几天数据,手工补一下就行”,这个念头省不了多少时间,却会埋下无数数据不一致的雷。直接回到第4节,重新mysqldump + CHANGE MASTER一条龙重做。

7. 主从配置完之后,还有三件事必须做

主从正常跑起来后,很多人就撤了。我建议你多留十五分钟,做下面三件事,能帮你日后避免很多麻烦。

7.1 配置监控:秒级告警必不可少

写一个简单的脚本,定时检查Slave_IO_Running、Slave_SQL_Running和Seconds_Behind_Master。贴上我常用的一个patch:

#!/bin/bash status=$(mysql -uroot -pYourPass -e "SHOW SLAVE STATUS\G" 2>/dev/null | grep -E "Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master") echo "$status" io=$(echo "$status" | grep Slave_IO_Running | awk '{print $2}') sql=$(echo "$status" | grep Slave_SQL_Running | awk '{print $2}') delay=$(echo "$status" | grep Seconds_Behind_Master | awk '{print $2}') if [ "$io" != "Yes" ] || [ "$sql" != "Yes" ] || [ "$delay" -gt 60 ]; then echo "MySQL Replication ERROR: IO=$io SQL=$sql Delay=$delay" # 这里可以接自己的告警通道,如短信、钉钉群里加一个webhook fi

这个脚本放到crontab里每1分钟跑一次。延迟阈值按业务定,60秒只是保守值。如果有超过两分钟的延迟,线上订单系统就会出问题,建议阈值再收紧。

7.2 备份策略:从库的binlog别浪费

既然从库也开了binlog(log_slave_updates = ON),那从库的binlog可以作为本地备份的基础。比如每天凌晨在从库做一次mysqldump,这样即使主库整个挂了,也能在从库上恢复,或者把从库提升为新主库(提升前需要先确认从库数据完全追平)。

还有一个小技巧:定期在从库上执行校验和,比如用pt-table-checksum(Percona Toolkit)比对主从的表是否一致。这是我处理过不少“主从数据静默不一致”问题的经验,光靠SHOW SLAVE STATUS根本发现不了这种问题。

7.3 写个“提主”操作文档

一主一从场景下,主库挂了,最紧急的操作是把从库提为主库。操作链路很简单:

  1. 确认从库已经追上主库最后的binlog。
  2. 在从库上执行STOP SLAVE; RESET SLAVE ALL;(要保留binlog就别RESET SLAVE ALL,只 STOP 即可)。
  3. 把从库的read_only改回OFF,super_read_only也改掉。
  4. 将业务流量切到新的主库。

但实际生产环境可能有多个从库,还可能有主从切换的工具(MHA、Orchestrator等),建议提前演练。第一次切主的时候手忙脚乱、执行错命令的概率极高,我自己的经验是,把切换命令文档放在从库服务器上,标上“降级预案”,比临时翻笔记强一万倍。

8. 最后说两个容易被忽略的细节

补充两个我实际工作中踩过的坑,都是配置上不起眼但后果严重的地方。

8.1 主库max_allowed_packet必须大于从库

MySQL复制本质是传输binlog事件。如果主库有一个大的存储过程或者大的批量插入,生成的binlog事件可能非常大。如果从库的max_allowed_packet配置小于主库,SQL线程会报Got a packet bigger than 'max_allowed_packet' bytes。建议在主从两边都设置成比较大的值,比如64M或128M,并且从库不能小于主库。这属于你在配置里顺手加上就能避免的麻烦。

8.2 不同版本之间的复制:字符集和排序规则

如果主库是8.0,从库是5.7(虽然我不推荐),字符集不一致会造成SQL线程报错。特别是如果主库的表用了utf8mb4_0900_ai_ci(MySQL 8.0默认排序规则),5.7根本不认识这个排序规则,同步的那张表在从库上会直接跳过或者建表失败。检查方法:

SELECT table_name, table_collation FROM information_schema.tables WHERE table_schema='db1';

如果排雷后发现不同,建议统一改成utf8mb4_general_ci,虽然是老排序规则,但兼容性最好。在自己负责的数据库里,我一般统一指定utf8mb4+utf8mb4_general_ci,宁可少用一点新特性的排序,也不要四处乱碰兼容性问题。


把上面这些步骤都走完,你的MySQL主从应该能稳定跑起来。这篇文章我从原理讲到配置,再讲到单表同步、故障排查和日常维护,基本覆盖了我这些年在生产环境折腾主从的核心经验。主从复制本身不是高可用方案的终点,它后面还连着读写分离、故障自动切换、数据备份这些话题,但底层的东西都在这了。如果你照着配完还碰到什么报错,欢迎在评论区把SHOW SLAVE STATUS\G的输出贴出来,我帮你一起看。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 22:52:46

魔百盒CM201-2长虹代工版免拆短接刷机全攻略

最近帮朋友刷了一台魔百盒CM201-2长虹代工版&#xff0c;刷完顺手换了桌面、去了开机广告&#xff0c;4K输出也正常了&#xff0c;朋友说比原来那个定制系统好用太多了。但说实话&#xff0c;这次折腾的过程并不顺利——短接点在不同批次的板子上居然还不一样&#xff0c;我第一…

作者头像 李华
网站建设 2026/9/28 22:52:17

树莓派5双MIPI接口实战:同时驱动CSI摄像头与DSI屏幕的完整配置指南

树莓派5刚发布那会儿&#xff0c;我第一时间入手了一块&#xff0c;冲着它那两个四通道MIPI接口去的。之前用树莓派4做视觉小车&#xff0c;CSI摄像头和DSI屏幕只能二选一&#xff0c;想同时接就得走HDMI或者SPI小屏&#xff0c;线缆一堆不说&#xff0c;刷新率和延迟都让人难受…

作者头像 李华
网站建设 2026/9/28 22:48:11

LMK04828时钟芯片配置实战:从引脚到JESD204B同步

1. 先搞清楚LMK04828到底在系统里扮演什么角色LMK04828这颗芯片&#xff0c;如果你只是翻数据手册&#xff0c;很容易被它那几十页的寄存器映射和密密麻麻的引脚定义劝退。但如果你手头正在调试一块高速ADC采集板或者JESD204B链路&#xff0c;那它大概率就是你绕不开的那道坎。…

作者头像 李华
网站建设 2026/9/28 22:46:43

AI工程实战:从零搭建可稳定运行的机器学习系统

1. AI工程的真正边界&#xff1a;它到底在解决什么问题老实说&#xff0c;我第一次看到“ai-engineering-from-scratch”这个项目名的时候&#xff0c;第一反应是“又一个模型微调教程”。但真正把整个体系捋下来之后&#xff0c;我发现事情远没有那么简单——它讲的不是怎么训…

作者头像 李华
网站建设 2026/9/28 22:46:07

人机协同工业质检落地:MCP协议与VLA模型工程化实践

1. 为什么“人机协同”不是口号&#xff0c;而是工业现场算得过账的必然选择1.1 从“机器换人”到“人机搭班”的认知转弯前几年聊工业智能化&#xff0c;十个人里有八个第一反应是“机器换人”——把产线上的工人换掉&#xff0c;把质检员换掉&#xff0c;把巡检工换掉。这个叙…

作者头像 李华
网站建设 2026/9/28 22:45:22

Flutter for OpenHarmony数独棋盘:CustomPaint绘制与数据模型实战

1. 为什么要在OpenHarmony上选Flutter画数独棋盘先交代一下项目背景。我手头有个数独游戏App&#xff0c;目标平台是OpenHarmony。一开始当然想用ArkTS直接写&#xff0c;毕竟那是OpenHarmony的"官方语言"&#xff0c;文档全、示例多。但团队之前的主力栈是Flutter&a…

作者头像 李华