//
MySQL错误日志激增案例
//
今天中午,搭建好的一套主从环境中磁盘报警,登陆到相关环境,发现是MySQL的错误日志量非常大,于是使用tail -f命令查看了日志文件,发现该错误日志增长的速度非常快,日志内容为:
--T19::46.697310+08: [Note]
Error log throttle: time(s) Error_code: "Slave SQL thread
ignored the query because of replicate-*-table rules" got suppressed.
--T19::46.697341+08: [Note]
Slave SQL for channel '': Worker failed executing transaction
'6d2f744e-XXXX-11e8-83f2-7cd30aeb120c:98514961' at master log
mysql-bin.817, end_log_pos ; Could not execute Query event.
Detailed error: Slave SQL thread ignored the query
because of replicate-*-table rules; Error log throttle is enabled.
This error will not be displayed for next secs.
It will be suppressed, Error_code:
从错误中不难看出来,是因为我们配置了replicate-*-table的复制过滤器,才导致某条SQL语句被复制过滤器过滤掉了,从库上没有执行该条语句,才导致了报警信息的发生,
ps.关于复制过滤器,之前写过一篇文章可以参考:
为了进一步确认问题,我查询了上面说到的二进制日志中的内容,我们可以使用"show binlog events in 'mysql-bin.001817' from 23565681;"的语法来查看该位置处的event事件,查看的结果如下:
CREATE TABLE IF NOT EXISTS mysql.ha_health_check ( id BIGINT DEFAULT 0, type CHAR(1) DEFAULT '0', PRIMARY KEY (type) )
该event的内容是一个创建表的SQL,该表是mysql系统数据库的内容,而我们的从库恰好过滤了mysql系统数据库的所有操作,如下:
问题已经很明显了,是因为这个赋值过滤器导致的问题。
解决办法
1、查官方文档
文章最后面的错误码1237给了我一点提示,于是先查询了MySQL官方文档的错误码:
https://dev.mysql.com/doc/refman/5.7/en/server-error-reference.html
嗯,找到了,如下所示,但是没有给出解决办法,似乎没什么用...
2、查MySQL bug讨论区
功夫不负有心人,找到了:
https://bugs.mysql.com/bug.php?id=73292
这个网站中有人遇到了跟我同样的问题,最终的解决办法是设置一个MySQL中的参数:--slave-skip-errors=1237,这个参数看样子是从库跳过某些错误代码的,查询了一下官方文档,官方文档中给出了该参数的一些信息和实例,如下:
从上面的信息来看,该参数是用来跳过一些特定错误码的错误的,如果要跳过多个错误,中间需要用逗号进行分割,除此之外,还有一句友情提醒:除非您清楚您自己在做什么,否则不要滥用这个参数,因为它的设置可能会导致主从不同步(我能来查这个参数,是不是意味着我不了解它...,不过由于是从库,还是尝试一下吧)。
于是我看了一下这个参数的值,默认是OFF的情况,首先尝试了一下在线直接修改,结果报错,该参数是一个只读的参数,修改必须重启服务,由于是从库,所以就直接重启修改了,修改前和修改后的值内容如下:
修改前
mysql--root@ :(none) ::>>show variables like '%slave_skip_errors%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| slave_skip_errors | OFF |
+------------------------+-------+
rows in set (. sec)
修改后
mysql--root@localhost:(none) ::>>show variables like '%slave_skip_errors%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| slave_skip_errors | 1237 |
+------------------------+-------+
rows in set (. sec)
再次启动从库,怀着激动的心情等待奇迹的诞生,结果..................还是报错,没什么用啊,看来别人的方法并不一定适合你~
3、接着google,看看其他办法
功夫又不负有心人,又让我找到一个percona的官方讨论网站:
https://www.percona.com/forums/questions-discussions/mysql-and-percona-server/33494-replication-warning-when-replicating-with-replicate-ignore-db
上面有一位老哥说了一段很有价值的话,如下:
可能看的不是很清楚,里面大概写了两三个参数,还给了一个twitter的网址,说他自己以前搞过一些研究,我本地打不开,就没追溯了,网好的兄弟可以进去看看。
我来说说这2个参数:log_warnings和log_error_verbosity,
其中,log-warnings参数解释如下:
全局参数,5.7.2之后,默认值是2,之前是1,
log_warnings 为0, 表示不记录告警信息。
log_warnings 为1, 表示告警信息写入错误日志。
log_warnings 大于1, 表示记录各类告警信息,包含一些连接被拒绝或者异常终止的连接信息。
该参数下面有个提示,就是从5.7.2开始,参数log_error_verbosity将优于log-warnings被加载。
这个信息比较重要,可以看出来,优于我们使用的是5.7.16,所以重点是关注log-error-verbosity参数,该参数的说明如下:
官方文档上写到:该参数表示了服务器将错误、警告和注释消息写入错误日志的详细程度。
1 (errors only),
2 (errors and warnings),
3 (errors, warnings, and notes)
看到这里,答案就比较明显了,该参数默认值是3,往错误日志里面写入错误,警告和注释,我们关闭掉那些不需要的注释即可,手工执行:
mysql--root@ :(none) ::>>show variables like '%log_err%';
+---------------------+----------------------------------------+
| Variable_name | Value |
+---------------------+----------------------------------------+
| binlog_error_action | ABORT_SERVER |
| log_error | /data/mysql_4306/log/mysqlerr_4306.err |
| log_error_verbosity | 3 |
+---------------------+----------------------------------------+
rows in set (. sec)
mysql--root@ :(none) ::>>set global log_error_verbosity=;
Query OK, rows affected (. sec)
再看错误日志,发现问题已经解决。
关于--slave-skip-errors参数,之前解决主从复制错误的时候,有提到过,详见文章:
虽然解决的问题比较小,但是还是值得记录一下的,万一以后一点用呢,哈哈
有帮助的话还希望点下再看哈