一套Master-Master Replication的MySQL集群,版本5.1.37。其中一个节点A出现OS异常重启,数据库启动后表现正常。但是没过多久另外一个节点B报错:
091127 21:50:21 [ERROR] Error reading packet from server: Client requested master to start replication from impossible position ( server_errno=1236) 091127 21:50:21 [ERROR] Got fatal error 1236: 'Client requested master to start replication from impossible position' from master when reading data from binary log 091127 21:50:21 [Note] Slave I/O thread exiting, read up to log 'mysql-bin.000535', position 193022771
Slave_IO_Running线程终止。仔细看上面的报错信息,说slave进程试图从mysql-bin.000535日志的position 193022771开始启动恢复,但是该日志中是没有这个position的。
跑到A上通过mysqlbinlog查看该日志,发现最后一个有效position是193009460。而要求的193022771已经大于最后有效的position了。这个原因就搞不明白了,难道是因为A库异常关闭后导致A节点的binlog没有来得及刷到磁盘,而B节点slave已经恢复到前面去了?
$mysqlbinlog mysql-bin.000535 > 1.txt $tail -n 7 1.txt # at 193009460 #091127 20:50:21 server id 1 end_log_pos 193009487 Xid = 194299849 COMMIT/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
尝试将B节点change master到最后一个有效的position处,问题暂时得到解决:
change master to master_log_file='mysql-bin.000535', master_log_pos=193009460
网上搜索了一把,发现logzgh之前也碰到过同样的问题,版本是5.0.51。

问题原因我一直觉得就是Master死之前,logbin有用os cache或者本身的cache机制,还没有写入磁盘,但是已经通过网络传递到Slave上了。跟Mysql版本关系不大。
Master如果没有在线应用在跑,死100次,我认为也不会遇到这个问题。
其实这种情况有日常Master和Slave数据周期校验保证的情况下,最好是切换到Slave,Slave数据MS从logbin来看更准确。
但是可能太多mysqldba都还是习惯等Master起来,再change一下。我也这么干,Master起不来了,再切换到Slave。