MySQL中继日志已损坏,如何解决?尝试过但失败了


25

当计算机突然关闭时,MySQL v5.1.61中继已损坏。我试图修复它,但是没有用。
- 我如何解决它?我做错什么了吗?

据我所知,损坏的MySQL中继日志很容易修复:

change master to master_log_file='<Relay_Master_Log_File>',
                 master_log_pos=<Exec_Master_Log_Pos>;

其中Relay_Master_Log_File和按Exec_Master_Log_Pos以下方式列出:
mysql> show slave status;

但是,当我这样做时change master status ...,出现了主键冲突错误。那怎么可能?上面的过程不正确,还是缺少一些+1?

(目前,我只是将--master-data mysqldump从主服务器重新导入到从服务器,这解决了问题。但是,将来,这样做可能不合适。)


以下是有关我的特定问题的详细信息:

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: the-master-host
                  Master_User: replication
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000021
          Read_Master_Log_Pos: 33639968
               Relay_Log_File: mysql-relay-bin.000271
                Relay_Log_Pos: 2031587
        Relay_Master_Log_File: mysql-bin.000020
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: the_database
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1594
                   Last_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 66395191
              Relay_Log_Space: 36559177
              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: 1594
               Last_SQL_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.

这就是我所做的:

mysql> stop slave;
mysql> reset slave;
mysql> change master to master_host='the-master-host', master_user='replication', master_password='the-password', master_log_file='mysql-bin.000020', master_log_pos=66395191;
mysql> start slave;

这就是发生的一个PK错误:

131122 15:17:29 [Note] Slave I/O thread: connected to master 'replication@the-master-host:3306',replication started in log 'mysql-bin.000020' at position 66395191
131122 15:17:29 [ERROR] Slave SQL: Error 'Duplicate entry '71373' for key 'PRIMARY'' on query. Default database: 'the_database'. Query: 'insert into ...  values ...', Error_code: 1062
131122 15:17:29 [Warning] Slave: Data truncated for column 'date' at row 1 Error_code: 1265
131122 15:17:29 [Warning] Slave: Duplicate entry '71373' for key 'PRIMARY' Error_code: 1062

我想我遵循了推荐的过程(请参见下面的链接),仍然出现PK错误:-(?http: //bugs.mysql.com/bug.php? id= 26489,搜索“替代方法”。 //mhbarr.wordpress.com/2013/07/26/mysql-slave-corrupted-relay-log/ /programming//a/14438408


1
是的,看起来它应该已经起作用了,实际上看起来似乎确实起作用了,因为在损坏部分之前,原始中继日志可能已经在该主日志位置进行了插入,但是无法前进因为该指针存储在中继日志中(损坏了),所以它显示了到下一个指针的主机位置。因此,您可能已经跳过了该事件并转到下一个事件,然后验证主机和从机实际上是否具有相同的数据...我还没有机会足够详细地审查问题。
Michael-sqlbot

1
感谢@ Michael-sqlbot,然后我认为如果再次发生此问题,我将SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;跳过从属设备上的一个事件,并希望能对您有所帮助-有意义吗?如果没有帮助(如果仍然存在PK错误),我将--master-data再次导入转储。
KajMagnus

Answers:


34

错误:Last_SQL_Errno:1594 Last_SQL_Error:中继日志读取失败:无法解析中继日志事件条目。

此错误意味着主日志文件已损坏或中继日志文件已损坏。

  • 在执行任何操作之前,请备份所有数据库,日志,图像服务器,重复多次,并且后果自负。

首先在从站上运行“显示从站状态\ G”,并注意:

Master_Log_File: mysql-bin.000026
Read_Master_Log_Pos: 2377104
Relay_Log_File: mysqld-relay-bin.000056
Relay_Log_Pos: 1097303
Relay_Master_Log_File: mysql-bin.000026
Exec_Master_Log_Pos: 1097157

首先,我们要确保主日志文件是完整的,因此跳转到主服务器上并找到Relay_Master_Log_File(检查/ var / log / mysql)并运行以下命令:

mysqlbinlog mysql-bin.000026

将显示日志,但希望您不会看到任何错误消息。如果您看到错误消息,则主日志已损坏,您可能必须重新映像。

接下来在从属中继日志上运行相同的命令(通常在/ var / lib / mysql中)

mysqlbinlog mysqld-relay-bin.000056

您可能会看到一些错误,显示已停止复制的损坏,例如:

ERROR: Error in Log_event::read_log_event(): 'read error', data_len: 336, event_type: 2
ERROR: Could not read entry at offset 1097414: Error in log format or read error.
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
root@db:/var/lib/mysql#

如果看到任何错误,则主服务器上的日志很好,只有从服务器的中继日志已损坏。这是个好消息,我们可以重置从属服务器,并告诉其主服务器详细信息以及从何处继续。如果您没有看到任何错误,请立即停止阅读,这是另一个问题。

如果从属中继日志有错误,请运行以下命令以重置从属并且损坏的日志重新连接到主服务器,获取确定的日志并再次开始从属。请注意,MASTER_LOG_POS是Exec_Master_Log_Pos,而MASTER_LOG_FILE是Relay_Master_Log_File不是第一个,它匹配已获取并需要丢弃的中继日志)两者都来自第一个命令。

mysql> stop slave;
Query OK, 0 rows affected (0.14 sec)

mysql> reset slave all;
Query OK, 0 rows affected (0.43 sec)

mysql>  CHANGE MASTER TO MASTER_HOST='master.host.com', MASTER_USER='masteruser', MASTER_PASSWORD='masterpass', MASTER_LOG_FILE='mysql-bin.000026', MASTER_LOG_POS=1097157;
Query OK, 0 rows affected (0.93 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

2
嗨,谢谢您的回答。如果您仔细阅读了该问题,您会发现它说“中继日志已损坏”-这是因为我们已经mysqlbinlog按照您的建议使用了,并发现中继日志(而非主日志)已损坏。提出建议的解决方案-如果您仔细阅读问题,您会发现建议的解决方案正是我们已经尝试过的解决方案。但这没有用,这就是问题所在。—但是您的答案可能对其他有类似问题的人有用。
KajMagnus 2014年

2
应该指出的是,MASTER_LOG_FILEin CHANGE MASTER应该取自Relay_Master_Log_File而不是Master_Log_File。通常它们是相同的,但并非总是如此(请参见percona.com/blog/2008/07/07/…)。
brablc

@brablc是正确的。Relay_Master_Log_File必须使用,而不是Master_Log_File。参见:percona.com/blog/2008/07/07/...
米尔恰Vutcovici

在大多数情况下,reset slave all不需要更改,因为不需要更改主设置(例如master_host,master_user,master_password),只需更改MASTER_LOG_FILE和MASTER_LOG_POS,reset_slave则应满足
ympostor

这个问题和答案已经救了我几次。谢谢。
Artem Russakovskii

8

[从属的中继日志损坏后修复MySQL复制]

从站(版本5.XX)上的MySQL复制已停止。Slave_IO_Running被标记为“是”,但是Slave_SQL_Running被标记为“否”。简单的停止/启动从站没有帮助,因此需要进一步的问题分析。似乎当前从站的中继日志已损坏,因为使用“ mysqlbinlog”进行的测试已打印出错误。因此,解决方案是丢弃当前的继电器二进制记录,并将从站指向最后一个主二进制记录位置。

要解决该错误,应丢弃从站上当前的binlog文件并设置新位置。在设置新的二进制日志位置之前,请务必使用命令SHOW SLAVE STATUS \ G从损坏的从属服务器中记住Relay_Master_Log_FileExec_Master_Log_Pos值:

Relay_Master_Log_File: mysql-bin.002045
Exec_Master_Log_Pos: 103641119

确定,使用此值,可以设置新的二进制日志位置:

# stop slave
mysql> stop slave;

# make slave forget its replication position in the master's binary log
mysql> reset slave;

# change slave to start reading from stopped position
mysql> change master to master_log_file='mysql-bin.002045', master_log_pos=103641119;

# start slave
mysql> start slave;

只是要注意,reset slave将删除master.inforelay-log.info并且所有的中继日志文件,所以它不是需要在清洁剩菜/var/lib/mysql目录。


1
好的答案-通常我们不需要更改主控主机,密码等。
andy250

3

我知道已经过去一年了,但是这个特殊问题可能已经发生了。

mysql> stop slave;
mysql> reset slave;
mysql> change master to master_host='the-master-host', master_user='replication', master_password='the-password', master_log_file='mysql-bin.000020', master_log_pos=66395191;
mysql> start slave;

看起来应该已经修复它,因为它删除了损坏的中继日志。

然后,您得到PK错误1062。为什么?

有一个未解决的错误(http://bugs.mysql.com/bug.php?id=60847)在MySQL 5.5中仍处于活动状态

尽管该错误与使用mysql --single-transaction --flush-logs有关,但存在一个相关的怪癖。

我上周在MySQL 5.5.15中看到了一些作为客户端的EC2服务器运行的怪癖

在主服务器上,有一个奇怪的多行扩展INSERT,其中插入的每个元组都是一个SELECT。发生的事情是中继日志中的LAST_INSERT_ID构成了要分配的下一个自动增量,因为先前已进行多行插入,所以该从属节点已在使用它。

中继日志中的序列化INSERT看起来像

INSERT INTO tablname (column,column) VALUES (value,value,...)

列列表不包含数字主键。当出现1062错误时,我将使用失败的同一查询,手动运行该查询。它没有遇到1062错误。然后,我运行了通常的跳过从属命令:

STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
START SLAVE;
SET @sleepnumber = SLEEP(3);
SHOW SLAVE STATUS\G

然后,复制赶上了。

我的建议是在Master上正确序列化您的INSERT,因为这种类似bug的情况实际上是可以避免的。


1

您做得很对(就像其他人已经说过的那样)。

唯一的问题是master.info文件(包含有关master的mysql-bin.log中位置的信息),因为在每次查询处理后,此文件都不会同步到磁盘。

因此,您有关主日志中位置的信息已过时,并且您正在处理已经处理过的查询,需要使用跳过这些查询SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;

不幸的是,如果您使用类似的查询,UPDATE table SET counter=counter+1 WHERE id = 12345并且使用binlog_format=STATEMENT的数据库可能不同步,我认为。

您可以通过设置变量sync_master_info来告诉MySQL服务器在每个事件之后同步master.info,但这可能会带来巨大的性能后果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.