美文网首页
案例分析:5.7从库偶尔truncate报表不存在的问题

案例分析:5.7从库偶尔truncate报表不存在的问题

作者: 重庆八怪 | 来源:发表于2023-03-23 11:45 被阅读0次

问题描述

最近遇到一个问题,主从每隔一段时间就报错tuncate表不存在,然后过一会start slave就能恢复,如下日志:

[ERROR] Slave SQL for channel '': Error 'Table '***.***' doesn't exist' on query. Default database: '***'. Query: 'TRUNCATE TABLE ***', Error_code: 1146
[Warning] Slave: Table '***.***' doesn't exist Error_code: 1146
[ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'mysql-bin.***' position ***.

相关时间点,没有其他的报错,且日志级别为3。

当然这里表做了屏蔽,但是错误就是这个。

检查项目

  • 表是否有主外键,触发器,结果为单表没有主键和外键无触发器
  • 是否有可能修改表的大小写,结果为没有修改过
  • 是否开启了MTS,结果为MTS关闭

看起来这个问题就比较奇怪了,关键是过一会start slave又正常了,又可以跑一段时间。

查找原因

然后我们仔细又分析了MySQL的error日志。发现虽然不是在主从报错的时间点,但是偶尔会出现这样的报错

Error in accept: Too many open files in system

很显然这是由于accept返回socket fd的时候由于最大打开文件数量限制导致的,继而查找mysqld的limit ,也就是/proc/mysqlpid/limits

image.png

可见这里没有问题,而且这个库表不多,理论上没有可能超过这个限制,继续查找我们发现系统的fs.file-max设置比较小为65535(sysctl.cnf),这是整个系统的,显然这很小了,因为这个服务器上还有很多其他的应用。

fs.file-max:This  file  defines a system-wide limit on the number of open files for all processes.

那么如果偶尔超过了限制fs.file-max是否会导致truncate报错Table '.' doesn't exist呢?理论上应该是有其他报错的比如上面的Too many open files in system。

接着在5.7种进行2种truncate 表不存在的测试:

  • frm文件不存在的情况下truncate table,报错Table '.' doesn't exist
  • frm文件存在,但是数据字典不存在的情况下,truncate table这个表也是报错Table '.' doesn't exist

但是两者的报错栈实际不是一个位置,前者是在open frm文件的时候见检查到错误了报错,后者是在通过innodb数据字典建立table share的时候发现信息不存在报错。那么结合这里的案例,前者的可能性更大,因为frm文件通常打开后会关闭,而不是一个常驻在fd,那么超过最大文件数就会导致打开frm报错,且如果innodb字典有问题再次start slave应该也会报错。那么,当超过最大打开文件数的时候打开frm文件是否会导致truncate出现这种问题呢?

接着就查看打开和检查frm相关的函数如下:


image.png

这里看起来确实没有打印errno和其相关的含义,而是直接return一个错误。

测试和修改

那么看起来就很像了,接着我们进行测试,这里使用如下的方式,

mysql client:
mysql> select version();
+------------+
| version()  |
+------------+
| 5.7.40-log |
+------------+
1 row in set (0.00 sec)

mysql> show variables like '%log_error_verbosity%';
+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| log_error_verbosity | 3     |
+---------------------+-------+
1 row in set (0.01 sec)

mysql> truncate table io;
Query OK, 0 rows affected (0.00 sec)

mysql> truncate table io;
Query OK, 0 rows affected (0.00 sec)

mysql> truncate table io;
Query OK, 0 rows affected (0.00 sec)

mysql> truncate table io;
Query OK, 0 rows affected (0.00 sec)

change os file-max 

vi /etc/sysctl.conf  add fs.file-max = 128
sysctl -p

back to mysql client

mysql> truncate table io;
ERROR 1146 (42S02): Table 'mytest.io' doesn't exist
mysql> drop table io;
ERROR 1051 (42S02): Unknown table 'mytest.io'

check mysql error log,no obvious error reported.

这样就能重现这个问题,如果在某一时刻正在做truncate但是这个时候超过file-max的设置,那么就会报这个错,而过后打开文件数关闭一些后再次启动start slave又恢复了,这实际上和主从关系不大。这个地方实际上只要加上errno的打印就好了,应该是报错不明显的问题,至少应该在日志文件打印如下日志:

2023-03-22T07:41:26.995765Z 2 [ERROR] Error in open frm file: ./t2/myt.frm, Too many open files in system
2023-03-22T07:41:36.834439Z 2 [ERROR] Error in open frm file: ./t2/myt.frm, Too many open files in system

但是提交BUG后发现(具体的重现和问题点也可以参见BUG),5.7已经不做这类修复了,只会做crash和安全的修复如下:
https://bugs.mysql.com/bug.php?id=110460

看来今年有大招要放啊。

相关文章

网友评论

      本文标题:案例分析:5.7从库偶尔truncate报表不存在的问题

      本文链接:https://www.haomeiwen.com/subject/oncirdtx.html