巡检的时候发现一个从库同步停止了,报错如下:
================================================================================================
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event; consider out of disk space on master; the first event '' at 4, the last event read from '/data/mysql_root/log/20120/mysql-bin.000007' at 330383340, the last byte read from '/data/mysql_root/log/20120/mysql-bin.000007' at 330383360.'
================================================================================================
根据报错提示,应该是主库空间问题,导致binlog日志被截断。分析故障原因:
该错误和主库空间问题以及sync_binlog配置有关,主库上sync_binlog的值为0,它表示binlog从os cache刷写到磁盘是由操作系统来控制的。由于存储日志的磁盘空间满导致MySQL没有将日志完全写入磁盘,binlog event被截断。slave读取该binlog时就会报错“binlog truncated in the middle of event”.
一般情况下的处理方式就是在从库上重新指向到主库下一个可用的binlog,并且从binlog file的初始化位置开始:
stop slave;
change master to master_log_file=’mysql-bin.000008’,master_log_pos=120;
start slave;
但是发现主库上并没有下一个binlog file :mysql-bin.000008,最新的binlog file就是mysql-bin.000007
在主库上查看binlog的开启情况:
非常诡异呀,开启了binlog,为什么show master status是空的???
查看主库binlog最后更新时间:
10月31号16:59分。而发现同步停止已经是11月1号早上九点多了!
所以很可能10月31号16:59分发生过什么严重的错误。于是查看error log,发现一堆如下报错:
2016-11-01 10:08:46 22661 [ERROR] vio_peer_addr get client ip error
2016-11-01 10:09:01 22661 [ERROR] vio_peer_addr get client ip error
2016-11-01 10:09:16 22661 [ERROR] vio_peer_addr get client ip error
2016-11-01 10:09:31 22661 [ERROR] vio_peer_addr get client ip error
........................................
这种蛋疼的报错,到google上查,什么都没查出来。所以要想查出什么蛛丝马迹,需要过滤掉这种混淆视线的错误!
cat /data1/mysql_root/data/20120/TENCENT64.site.err | grep -v "vio_peer_addr"
然后根据时间来过滤,查找相应时间段发生了什么错误,发现错误信息如下:
2016-1031 16:57:42 22661 [Warning] Disk is full writing '/data/mysql_root/log/20120/mysql-bin.000007' (Errcode: 28 - No space left on device). Waiting for someone to free space...
2016-10-31 16:57:42 22661 [Warning] Retry in 60 secs. Message reprinted in 600 secs
2016-10-31 16:59:42 22661 [ERROR] An error occurred during flush stage of the commit. 'binlog_error_action' is set to 'IGNORE_ERROR'. Hence turning logging off for the whole duration of the MySQL server process. To turn it on again: fix the cause, shutdown the MySQL server and restart it.
果然是发生了磁盘空间满的问题。并且可以很明显地看到有一个报错:
'binlog_error_action' is set to 'IGNORE_ERROR'. Hence turning logging off for the whole duration of the MySQL server process. To turn it on again: fix the cause, shutdown the MySQL server and restart it.
从MySQL 5.6.22版本开始,引入了一个新参数binlog_error_action (5.6.20及21版本叫做binlogging_impossible_mode),若设置为ABORT_SERVER,则在发生binlog写入错误时直接让实例退出,避免引发更大的错误;若设置为IGNORE_ERROR,则忽略本次写入失败,同时禁止Binlog记录,需要重启才能让binlog再次开启。为了主备数据的强一致性,通常应该将binlog_error_action设置为ABORT_SERVER,这样在打开文件、rotate新文件、从IO Cache写binlog到文件出现磁盘错误时,都会退出实例。
很明显,现在是只能重启主库,才能再次开启binlog。但是如果关闭主库,由于高可用自动切换,会将业务切到从库,而从库很明显从10月31号 16:59分的样子,同步就断掉了。如果直接切从机,从机的数据不是最新的,会发生业务故障。
解决办法就是:
控制不自动切从库,快速重启主库,binlog能正常记录之后,重建从库!