mysql主从复制报错怎么处理_mysql复制错误日志解析

来源:这里教程网 时间:2026-02-28 20:46:02 作者:

SHOW SLAVE STATUS\G
先锁定是 IO 还是 SQL 线程挂了

这是所有排查的起点,不是可选动作。登录从库执行这条命令后,只盯两行:

Slave_IO_Running
Slave_SQL_Running
。如果其中一个是
No
,就立刻分清战场:

Slave_IO_Running: No
→ 问题出在“拿不到日志”:主库连不上、binlog 文件名/位置错、权限不对、网络被拦(比如防火墙关了 3306 或 SELinux 没关)
Slave_SQL_Running: No
→ 问题出在“执行不了日志”:数据冲突(
1062
)、记录找不到(
1032
)、外键不满足(
1452
)、中继日志损坏(
1594

再顺手扫一眼

Last_IO_Error
Last_SQL_Error
字段——它直接告诉你错误码和原始语句,比翻日志快十倍。别跳过这步,很多人卡在反复重启却没看这一行。

查错误日志前先确认
log_error
路径

MySQL 错误日志不总在

/var/log/mysqld.log
,尤其容器或自定义部署环境。先执行:
mysql> SHOW VARIABLES LIKE 'log_error';

拿到真实路径后再
tail -n 50 /path/to/error.log
。重点找这些关键词:

Connection refused
timeout
Can't connect to master
→ 网络或主库 mysqld 没监听外网(检查
bind-address
是否为
0.0.0.0
Table doesn't exist
Unknown database
→ 从库缺库/表,不是数据不一致,是结构根本没同步过去
Relay log read failure
Event crc check failed
→ 中继日志损坏,不能硬跳过,得开
relay_log_recovery=1
并重启 MySQL
disk full
No space left on device
→ 磁盘满了,relay log 写不进,清理空间比修复制更紧急

mysqlbinlog
反查出错那条 SQL

Last_SQL_Error
提到 “Duplicate entry '1001' for key 'PRIMARY'”,光删从库数据不够,得知道主库当时执行的是哪条 INSERT。方法是:

SHOW SLAVE STATUS\G
中抄出
Relay_Master_Log_File
Exec_Master_Log_Pos
去主库执行:
mysqlbinlog --base64-output=DECODE-ROWS -v /var/lib/mysql/<code>mysql-bin.000006
| grep -A 5 -B 5 "end_log_pos 12345"(把文件名和位点替换成实际值)

输出里会看到完整 SQL 和涉及的库表字段。注意:MySQL 5.7+ 默认

binlog_format=ROW
,所以看到的是
### UPDATE ... ### WHERE
这类解析后内容,不是原始语句——但这反而更准,能看清具体哪一行被改。

跳过错误要分场景,
sql_slave_skip_counter
不是万能膏药

这个变量只能跳过当前事件(一条语句),但有严格前提:

仅适用于
STATEMENT
或混合模式;
ROW
格式下跳过可能跳掉多行更新,导致数据不一致
必须停掉复制:
STOP SLAVE;
,再设:
SET GLOBAL sql_slave_skip_counter = 1;
,再
START SLAVE;
遇到
1590
(LOST_EVENTS)、
1594
(relay log 损坏)这类系统级错误,跳过无效,必须重建 relay log 或重配主从
GTID 模式下完全禁用
sql_slave_skip_counter
,得用
SET GTID_NEXT
+ 空事务方式绕过

真正危险的不是报错本身,而是跳过之后没人验证从库数据是否还跟主库对得上。线上操作前,至少用

pt-table-checksum
抽样比对一次关键表。

相关推荐