阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

MySQL从库服务器down机报错Could not parse relay log event entry

108次阅读
没有评论

共计 9476 个字符,预计需要花费 24 分钟才能阅读完成。

环境介绍:

最近网站总是出问题,因为 play 服务总是跑着跑着就死了,于是经理尝试把 play 跑在我的 MySQL 这两台服务器上(因为这两台服务器的资源很空闲),可是没想到才跑了半天,就把服务器的 128G 内存耗尽,服务器无法正常使用,输入任何命令都报错,无法分配内存,reboot 都不可以,只能去机房强制关机了。

我这里一两台,主主复制的 mysql:

192.10.0.143

192.10.0.144

通过 keepalived 映射出来了 vip:192.10.0.145,目前 vip 在 144 上。

重启的是 143.

启动之后,mysql 服务成功开启了,可是主从状态报错,sql 进程状态为 NO, 如下:

MariaDB [(none)]> show slave status\G;

*************************** 1. row ***************************

Slave_IO_State: Waiting for master to send event

Master_Host: 192.168.0.144

Master_User: info_syncer

Master_Port: 3306

Connect_Retry: 60

Master_Log_File: mysql-bin.000823

Read_Master_Log_Pos: 60049919

Relay_Log_File: mysql-relay-bin.000047

Relay_Log_Pos: 268334387

Relay_Master_Log_File: mysql-bin.000822

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: 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: 268334100

Relay_Log_Space: 535066509

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.

Replicate_Ignore_Server_Ids:

Master_Server_Id: 2

Master_SSL_Crl:

Master_SSL_Crlpath:

Using_Gtid: No

Gtid_IO_Pos:

1 row in set (0.00 sec)

ERROR: No query specified

报错原因:

从上面红体字可以知道,由于从库的异常关机,导致接收的主库的二进制日志崩溃,进而导致从库的 relay 日志损坏,sql 进程无法读取,导致从库的 sql 进程状态为:NO。

问题解决:

MariaDB [(none)]> stop slave ;

Query OK, 0 rows affected (0.00 sec)

解决方法一:

找到,第一行记录了当前正在执行的 log-relay 文件名

找到该文件的下一个文件

使用 mysqlbinlog 查看该文件,在 #98 这行有 Rotate to log-bin.000004 pos: 4 等信息,这就是目前 slave 停止的位置,或者

在 slave 上重新指定同步位置,重新执行:

change master to

master_host=’1.1.1.1′,

master_user=’repl’,

master_password=’111111′,

master_port=3306,

master_log_file=’log-bin.000004′,

master_log_pos=4;

然后启动 slave,

start slave ;

解决方法二:

stop slave 之后,重新 reset slave;

查看 slave 状态,正常了。。。。。

reset slave 到底做了什么??

RESET SLAVE

官方的解释如下

1)RESET SLAVE makes the slave forget its replication position in the master’s binary log. This statement is meant to be used for a clean start: It clears the master info and relay log info repositories, deletes all the relay log files, and starts a new relay log file. It also resets to 0 the replication delay specified with the MASTER_DELAY option to CHANGE MASTER TO. To use RESET SLAVE, the slave replication threads must be stopped (use STOP SLAVE if necessary).

2)RESET SLAVE does not change any replication connection parameters such as master host, master port, master user, or master password, which are retained in memory. This means that START SLAVE can be issued without requiring a CHANGE MASTER TO statement following

reset slave

其实,它是直接删除 master.info 和 relay-log.info 文件,并删除所有的 relay log,然后重新生成一个新的 relay log,即使 relay log 中还有 SQL 没有被 SQL 线程 apply 完。

但是 RESET SLAVE 有个问题,它虽然删除了上述文件,但内存中的 change master 信息并没有删除,此时,可直接执行 start slave,但因为删除了 master.info 和 relay-log.info,它会从头开始接受主的 binlog 并应用。(注意:这里所说的从头是说:reset 的时候,正在接受的主的 binlog, 从新接受这个 binlog). 如果 SQL thread 正在复制临时表的过程中,执行了 stop slave,并且执行了 reset slave,这些被复制的临时表将被删除。

题外话:reset master 做了什么?

1. reset master 将删除日志索引文件中记录的所有 binlog 文件,创建一个新的日志文件 起始值从 000001 开始,

2. reset master 不能用于有任何 slave 正在运行的主从关系的主库。因为在 slave 运行时刻 reset master 命令不被支持,reset master 将 master 的 binlog 从 000001 开始记录,slave 记录的 master log 则是 reset master 时主库的最新的 binlog, 从库会报错无法找的指定的 binlog 文件。

继续解决问题:

主从状态正常后,查看告警日志,发现报错

告警日志报错:表 crashed,需要 repaire

ERROR] log.logs: 1 client is using or hasn’t closed the table properly

170310 11:54:14 [ERROR] mysqld: Table ‘./log/oprlogs’ is marked as crashed and should be repaired

170310 11:54:14 [Warning] Checking table:  ‘./log/oprlogs’

170310 11:54:14 [ERROR] log.oprlogs: 1 client is using or hasn’t closed the table properly

170310 11:54:14 [ERROR] log.oprlogs: Size of datafile is: 1656831165      Should be: 1656830670

170310 11:54:47 [ERROR] log.oprlogs: Found 495 deleted space.  Should be 0

170310 11:54:47 [ERROR] log.oprlogs: Found 15 deleted blocks      Should be: 0

170310 11:54:47 [ERROR] log.oprlogs: Found 50207005 key parts. Should be: 50206990

170310 11:54:47 [ERROR] mysqld: Table ‘./log/history’ is marked as crashed and should be repaired

170310 11:54:47 [Warning] Checking table:  ‘./log/history’

170310 11:54:47 [ERROR] log.history: 1 client is using or hasn’t closed the table properly

直接 repair table table_name 就可以了。。。。,依次修复日志中出现的被标记为 crashed 的表。

MariaDB [(none)]> repair  table  log.logs;

下面讲下修复 table:整理自网络。。。。。

多数情况下, 数据库被破坏只是指索引文件受到了破坏, 真正的数据被破坏掉的情况非常少。大多数形式的数据库破坏的的修复相当简单。

和前面的校验一样, 修复的方式也有三种。

下面讲的方法只对 MyISAM 格式的表有效。其他类型的损坏需要从备份中恢复。

1,REPAIR TABLE SQL statement(mysql 服务必须处于运行状态)。

2, 命令 mysqlcheck(mysql 服务可以处于运行状态)。

3, 命令 myisamchk(必须停掉 mysql 服务, 或者所操作的表处于不活动状态)。

在修复表的时候, 最好先作一下备份。所以你需要两倍于原始表大小的硬盘空间。请确保在进行修复前你的硬盘空间还没有用完。

1> 用”repair table”方式修复

语法:repair table 表名 [选项]

选项如下:

QUICK 用在数据表还没被修改的情况下, 速度最快

EXTENDED 试图去恢复每个数据行, 会产生一些垃圾数据行, 万般无奈的情况下用

USE_FRM 用在.MYI 文件丢失或者头部受到破坏的情况下。利用.frm 的定义来重建索引

多数情况下, 简单得用”repair table tablename”不加选项就可以搞定问题。但是当.MYI 文件丢失或者头部受到破坏时, 这样的方式不管用, 例如:

mysql> REPAIR TABLE mytable;

+————————-+——–+———-+———————————————+

| Table | Op | Msg_type | Msg_text |

+————————-+——–+———-+———————————————+

| sports_results.mytable | repair | error | Can’t find file:‘mytable.MYI’(errno: 2) |

+————————-+——–+———-+———————————————+

修复失败的原因时索引文件丢失或者其头部遭到了破坏, 为了利用相关定义文件来修复, 需要用 USE_FRM 选项。例如:

mysql> REPAIR TABLE mytable USE_FRM;

+————————-+——–+———-+————————————+

| Table | Op | Msg_type | Msg_text |

+————————-+——–+———-+————————————+

| sports_results.mytable | repair | warning | Number of rows changed from 0 to 2 |

| sports_results.mytable | repair | status | OK |

+————————-+——–+———-+————————————+

我们可以看到 Msg_test 表项的输出信息”ok”, 表名已经成功修复受损表。

2> 用 mysql 内建命令 mysqlcheck 来修复

当 mysql 服务在运行时, 也可以用 mysql 内建命令 mysqlcheck 来修复。

语法:mysqlcheck -r 数据库名 表名 -uuser -ppass

%mysqlcheck -r sports_results mytable -uuser -ppass

sports_results.mytable OK

利用 mysqlcheck 可以一次性修复多个表。只要在数据库名后列出相应表名即可 (用空格隔开)。或者数据库名后不加表名, 将会修复数据库中的所有表, 例如:

%mysqlcheck -r sports_results mytable events -uuser -ppass

sports_results.mytable OK

sports_results.events OK

%mysqlcheck -r sports_results -uuser -ppass

sports_results.mytable OK

sports_results.events OK

3> 用 myisamchk 修复

用这种方式时,mysql 服务必须停掉, 或者所操作的表处于不活动状态 (选项 skip-external-locking 没被使用)。记着一定要在相关.MYI 文件的路径下或者自己定义其路径。

语法:myisamchk [选项] [表名]

下面是其选项和描述

–backup, -B 在进行修复前作相关表得备份

–correct-checksum 纠正校验和

–data-file-length=#, -D # 重建表时, 指定数据文件得最大长度

–extend-check, -e 试图去恢复每个数据行, 会产生一些垃圾数据行, 万般无奈的情况下用

–force, -f 当遇到文件名相同的.TMD 文件时, 将其覆盖掉。

keys-used=#, -k # 指定所用的 keys 可加快处理速度, 每个二进制位代表一个 key. 第一个 key 为 0

–recover, -r 最常用的选项, 大多数破坏都可以通过它来修复。如果你的内存足够大, 可以增大参数 sort_buffer_size 的值来加快恢复的速度。但是遇到唯一键由于破坏而不唯一 的表时, 这种方式不管用。

–safe-recover -o 最彻底的修复方式, 但是比 - r 方式慢, 一般在 - r 修复失败后才使用。这种方式读出 所有的行, 并以行为基础来重建索引。它的硬盘空间需求比 - r 方式稍微小一点, 因 为它没创建分类缓存。你可以增加 key_buffer_size 的值来加快修复的速度。

–sort-recover, -n mysql 用它类分类索引, 尽管结果是临时文件会非常大

–character-sets-dir=… 包含字符集设置的目录

–set-character-set=name 为索引定义一个新的字符集

–tmpdir=path, -t 如果你不想用环境变量 TMPDIR 的值的话, 可以自定义临时文件的存放位置

–quick, -q 最快的修复方式, 当数据文件没有被修改时用, 当存在多键时, 第二个 - q 将会修改 数据文件

–unpack, -u 解开被 myisampack 打包的文件

myisamchk 应用的一个例子

% myisamchk -r mytable

– recovering (with keycache) MyISAM-table‘mytable.MYI’

题外引申。。。

REPAIR TABLE `table_name` 修复表

OPTIMIZE TABLE `table_name` 优化表

REPAIR TABLE 语句被写入二进制日志中,除非使用了自选的 NO_WRITE_TO_BINLOG 关键词(或其别名 LOCAL)。

REPAIR TABLE 用于修复被破坏的表。

OPTIMIZE TABLE 用于回收闲置的数据库空间,当表上的数据行被删除时,所占据的磁盘空间并没有立即被回收,使用了 OPTIMIZE TABLE 命令后这些空间将被回收,并且对磁盘上的数据行进行重排(注意:是磁盘上,而非数据库)。多数时间并不需要运行 OPTIMIZE TABLE,只需在批量删除数据行之后,或定期(每周一次或每月一次)进行一次数据表优化操作即可,只对那些特定的表运行。

从新 chang 的日志位置和日志号

无论是新搭建主从复制,还是

在拷贝之前要先锁定数据,然后再获得相关的日志信息(FILE & POSITION):

mysql> FLUSH TABLES WITH READ LOCK;        锁表,一般新加主从的时候,保重一致性

MariaDB [log]> SHOW MASTER STATUS;

+——————+———–+————–+————————–+

| File            | Position  | Binlog_Do_DB | Binlog_Ignore_DB        |

+——————+———–+————–+————————–+

| mysql-bin.000825 | 287366341 |              | mysql,information_schema |

+——————+———–+————–+————————–+

1 row in set (0.00 sec)

接下来拷贝数据文件时,如果是 MyISAM 表类型的话,直接拷贝即可;如果是 InnoDB 表类型的话,一定要先停止 MySQL 服务再拷贝,否则拷贝文件可能无法使用。把拷贝的数据文件直接复制到从服务器的数据目录。

最后还需要再指定一下日志信息:

mysql> CHANGE MASTER TO

MASTER_HOST=”<MASTER_HOST>”,

MASTER_USER=”<SLAVE_USER>”,

MASTER_PASSWORD=”<SLAVE_PASSWORD>”,

MASTER_LOG_FILE=”<FILE>”,

MASTER_LOG_POS=<POSITION>;

在主服务器上直接拷贝数据文件虽然很快,但需要锁表或者停止服务,这会影响线上服务。如果先前已经有了从服务器,那么可以用旧的从服务器做母本来克隆新的从服务器:

先在旧的从服务器上查询日志信息:

mysql> SHOW SLAVE STATUS;

我们需要的是其中的 Relay_Master_Log_File & Exec_Master_Log_Pos。

然后在旧的从服务器上按照前面的方法得到数据,可以先 stop slave,然后拷贝数据并在新的从服务器上还原。

接着在新的从服务器上设置日志信息:

mysql> CHANGE MASTER TO

MASTER_HOST=”<MASTER_HOST>”,

MASTER_USER=”<SLAVE_USER>”,

MASTER_PASSWORD=”<SLAVE_PASSWORD>”,

MASTER_LOG_FILE=”<Relay_Master_Log_File>”,

MASTER_LOG_POS=<Exec_Master_Log_Pos>;

不管用那个方法,最后记得在从服务器上启动复制,并检查工作是否正常:

mysql> START SLAVE;

mysql> SHOW SLAVE STATUS;

注意:

MariaDB [(none)]> show slave status\G;

显示的 Master_Log_File 和 Read_Master_Log_Pos 这两个只对应这 master

show master  status\G; 的文件号和位置

*************************** 1. row ***************************

Slave_IO_State: Waiting for master to send event

Master_Host: 192.168.0.143

Master_User: info_syncer

Master_Port: 3306

Connect_Retry: 60

Master_Log_File: mysql-bin.000019

Read_Master_Log_Pos: 1038

总结:万不得一不要在服务还没有停的情况下去停服务器,尤其是数据库,否则会出现意想不到的错误,但是当服务器出现不可解决的问题的时候,一定要果断的去重启,不要犹豫,难免出现更严重的问题,再就是 play 或者 tomcat 等等这些服务最好分开跑,以免互相影响。

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2017-03/141913.htm

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-22发表,共计9476字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中