当计算机突然关闭时,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_FileExec_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,搜索“替代方法” 。
http://mhbarr.wordpress.com/2013/07/26/mysql-slave-corrupted-relay-log/
https://stackoverflow.com/a/14438408

评论

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

感谢@ Michael-sqlbot,然后我认为如果再次出现此问题,我将执行SET GLOBAL sql_slave_skip_counter = 1;开始从动并跳过奴隶上的一个事件,并希望能有所帮助-有意义吗?如果没有帮助(如果仍然存在PK错误),我将再次使用--master-data导入转储。

#1 楼

错误:Last_SQL_Errno:1594
最后一个SQL_错误:中继日志读取失败:无法解析中继日志事件条目。

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


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

首先运行“在从属服务器上显示从属服务器状态\ 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)


评论


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

– KajMagnus
2014年8月28日在18:28



应该注意的是,CHANGE MASTER中的MASTER_LOG_FILE应该来自Relay_Master_Log_File,而不是Master_Log_File。通常它们是相同的,但并非总是如此(请参阅percona.com/blog/2008/07/07/…)。

– brablc
16年3月3日在10:07

@brablc是正确的。必须使用Relay_Master_Log_File,而不是Master_Log_File。另请参阅:percona.com/blog/2008/07/07/…

– Mircea Vutcovici
16 Sep 6 '15:31



在大多数情况下,不需要重置所有从属设备,因为不需要更改主设置(例如master_host,master_user,master_password),只需更改MASTER_LOG_FILE和MASTER_LOG_POS,然后reset_slave就足够了

–符号发布者
17年7月14日在3:15

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

– Artem Russakovskii
19年6月2日在23:29

#2 楼

[奴隶的中继日志损坏后修复MySQL复制]


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

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

Relay_Master_Log_File: mysql-bin.002045
Exec_Master_Log_Pos: 103641119


请注意,reset slave会删除master.inforelay-log.info和所有中继日志文件,因此不需要清理/var/lib/mysql目录中的剩余内容。


评论


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

– andy250
19-2-27在11:46

#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服务器运行的怪癖

在Master上,有一个奇怪的多行扩展INSERT,其中插入的每个元组都是一个SELECT 。发生的事情是,中继日志中的LAST_INSERT_ID构成了要分配的下一个自动增量,因为先前已经有多行插入,所以已经在Slave上使用了。

中继日志中的序列化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


然后复制就遇到了。

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

#4 楼

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

唯一的问题是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,但它可能具有巨大的性能后果。