如何调试MySQL主从复制错误1049?
问题描述
此前正常运行的MySQL主从复制突发故障,执行SHOW SLAVE STATUS\G后显示Slave_SQL_Running: No,错误码1049(未知数据库),需解决:
- 是否要执行
STOP SLAVE/START SLAVE重启? - 如何定位不存在的数据库?
- 怎么修复该故障?
主从节点配置
主节点配置
bind-address = 185.128.xxx.xxx server-id = 1 log_bin = /var/log/mysql/mysql-bin.log binlog_do_db = my_db_name
从节点配置
server-id = 2 max_binlog_size = 100M # log_bin = /var/log/mysql/mysql-bin.log binlog_do_db = my_db_name relay-log = /var/log/mysql/mysql-relay-bin.log
SHOW SLAVE STATUS\G输出(中文翻译)
*************************** 1. row *************************** Slave_IO_State: 等待源发送事件 Master_Host: 185.128.xxx.xxx Master_User: replica Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 2456753 Relay_Log_File: mysql-relay-bin.000003 Relay_Log_Pos: 1595182 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 1049 Last_Error: 协调器因工作线程出错而停止。最近一次失败为:工作线程1在源日志mysql-bin.000002的end_log_pos 1595341处执行事务'ANONYMOUS'失败。有关此失败或其他失败的更多详细信息,请查看错误日志和/或performance_schema.replication_applier_status_by_worker表。 Skip_Counter: 0 Exec_Master_Log_Pos: 1594966 Relay_Log_Space: 2457347 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 1049 Last_SQL_Error: 协调器因工作线程出错而停止。最近一次失败为:工作线程1在源日志mysql-bin.000002的end_log_pos 1595341处执行事务'ANONYMOUS'失败。有关此失败或其他失败的更多详细信息,请查看错误日志和/或performance_schema.replication_applier_status_by_worker表。 Replicate_Ignore_Server_Ids: Master_Server_Id: 1 Master_UUID: 42e23b0a-9fec-11ea-a6a6-00163e051c80 Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: 230810 13:58:36 Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: Master_public_key_path: Get_master_public_key: 0 Network_Namespace: 1 row in set, 1 warning (0.00 sec)
排查与修复步骤
1. 直接重启Slave没用
当前Slave_SQL_Running为No的核心原因是事务执行时找不到目标数据库,重启复制只会重复执行失败的事务,问题依然存在,先别直接重启,先定位问题。
2. 定位不存在的数据库
查看从节点错误日志
登录从节点,查看MySQL错误日志(默认路径为/var/log/mysql/error.log),日志会明确记录事务涉及的缺失数据库名称:tail -n 50 /var/log/mysql/error.log查询performance_schema表
在从节点执行以下SQL,获取失败事务的具体操作详情:SELECT * FROM performance_schema.replication_applier_status_by_worker\G结果里会显示失败的SQL语句,从中可找到对应的数据库名称。
解析主节点binlog
如果上述方法没找到,在主节点解析对应binlog文件,查看失败位置附近的SQL:mysqlbinlog --start-position=1594966 --stop-position=1595341 /var/log/mysql/mysql-bin.000002起始位置用
Exec_Master_Log_Pos的值(1594966),结束位置用错误信息中的end_log_pos(1595341),直接定位到失败的SQL。
3. 修复故障
情况一:从节点确实缺少该数据库
如果该数据库是业务必需的,直接在从节点创建:CREATE DATABASE IF NOT EXISTS 缺失的数据库名;然后启动SQL线程即可,无需重启整个Slave:
STOP SLAVE SQL_THREAD; START SLAVE SQL_THREAD;情况二:该数据库无需同步
如果是主节点临时创建的非业务库,可跳过这个失败的事务:STOP SLAVE; SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;之后执行
SHOW SLAVE STATUS\G确认Slave_SQL_Running变为Yes。
4. 优化配置避免再次出现
当前主从节点用的binlog_do_db = my_db_name存在逻辑缺陷:只有主节点会话默认数据库是my_db_name时,操作才会写入binlog。如果主节点执行USE 其他库; INSERT INTO my_db_name.tbl ...或直接操作其他库,可能导致binlog记录异常,或从节点执行时找不到库。
建议改用binlog_ignore_db(忽略不需要同步的库),或在从节点用replicate_wild_do_table = my_db_name.%配置更精确的同步规则。
内容的提问来源于stack exchange,提问作者Martin AJ

