暂无图片
暂无图片
5
暂无图片
暂无图片
暂无图片

“Cannot open './dbxxx/tbxxx.ibd'”不一定是文件损坏,记录一起文件句柄数引发的错误

原创 金同学 2025-02-17
185

案例

当数据库出现 Cannot open './kd_drp/t_occpic_rebatemonthly.ibd’这类错误时,一般都是文件损坏后无法打开表空间。但是今天分享案例是由于open files限制引起的。

2025-02-15T23:05:53.254309+08:00 4 [ERROR] [MY-012592] [InnoDB] Operating system error number 24 in a file operation.``` 2025-02-15T23:05:53.254323+08:00 4 [ERROR] [MY-012596] [InnoDB] Error number 24 means 'Too many open files' 2025-02-15T23:05:53.254332+08:00 4 [Note] [MY-012597] [InnoDB] Refer to your operating system documentation for operating system error code information. 2025-02-15T23:05:53.254340+08:00 4 [Warning] [MY-012093] [InnoDB] Cannot open './kd_drp/t_occpic_rebatemonthly.ibd'. Have you deleted .ibd files under a running mysqld server?
复制

mysql error.log出现上面错误,实例无法启动。

1、报错原因

mysql配置文件中设置了open_files_limit参数,这个参数对mysql进程有效,所以mysql服务只能使用到65535个文件,文件数不够时出现上文报错。

[root@0i fd]# cat /data/mysql/conf/my.cnf |grep open_files_limit open_files_limit = 65535
复制

2、解决方法

调大my.cnf中的open_files_limit参数的值后,故障恢复。如果my.cnf没有指定open_files_limit参数,则会通过其他方式获取。
建议:mysql进程获取limit限制参数的途径较多,为了保证其够用,遵循一个原则,同时调整大root用户、运行mysql服务的普通用户以及my.cnf中的open_files_limit。最终,mysql使用的limit参数值可查看/proc/pidof mysqld/limits文件。

root@localhost: 14:14: [(none)]> show variables like 'open_files_limit'; +------------------+--------+ | Variable_name | Value | +------------------+--------+ | open_files_limit | 524288 | +------------------+--------+ 1 row in set (0.01 sec)
复制

实例启动后,mysql进程有一套自己的limit参数值,而非操作系统看到的limit.conf中的值。下面代码中的Max open files就是最大文件打开数,与数据库中查到的open_files_limit对应。

cat /proc/`pidof mysqld`/limits Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 524288 524288 processes Max open files 524288 524288 files Max locked memory 65536 65536 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 127832 127832 signals Max msgqueue size 819200 819200 bytes
复制

3、open_files_limit 赋值优先级

赋予open_files_limit的值时,不同启动方式下的结果不同,优先级顺序如下:
(这里分享的结论只供参考,如有问题,欢迎评论区交流。)

首先,my.cnf中open_files_limit优先级最高,只要加了这个参数,就会覆盖其他方式获取的值。
其次,当没有open_files_limit参数时,分mysqld和mysqld_safe两种启动方式:

  1. mysqld启动时,读取当前用户下limit.conf中的最大文件打开数。即root用户启动时,读取root用户下的limits.conf文件,mysql用户启动时,读取mysql用户下的limits.conf文件。
  2. mysqld_safe启动时,mysql会调用my_print_defaults方法计算一个值(具体计算规则见下文),然后使用ulimit -n修改当前bash,然后被数据库读取。因此,mysqld_safe会忽略当前用户下的limit.conf中的值。

下面是mysqld_safe脚本修改open files相关的两段代码。

# Get first arguments from the my.cnf file, groups [mysqld] and [mysqld_safe] # and then merge with the command line arguments if test -x "$MY_BASEDIR_VERSION/bin/my_print_defaults" ; then print_defaults="$MY_BASEDIR_VERSION/bin/my_print_defaults" elif test -x "/usr/local/mysql/bin/my_print_defaults" ; then print_defaults="/usr/local/mysql/bin/my_print_defaults" else print_defaults="my_print_defaults" fi
复制
USER_OPTION="" if test -w / -o "$USER" = "root" then if test "$user" != "root" -o $SET_USER = 1 then USER_OPTION="--user=$user" fi if test -n "$open_files" then ulimit -n "$open_files" fi fi if test -n "$open_files" then append_arg_to_args "--open-files-limit=$open_files" fi
复制

所以,open_file_limit的值来源较多,运维过程中需要关注。另外,在数据库升级过程中,mysql会打开所有表,所需文件数更多,需要预留一个较大的值。

my.cnf不设open_files_limit参数时,其计算规则如下,选择下面两种算法中较大的值:

  • 10 + max_connections + (table_open_cache * 2)
  • max_connections * 5

扩展:关于参数innodb_open_files

上文中的open_files_limit对整个实例有效,而innodb_open_files参数控制innodb层同时打开的文件数量(open),且文件数大于参数值也不会报错,它会通过LRU链表淘汰。这一点与open_files_limit是不一样的。
在生产中建议设置一个小于open_files_limit的值(大概少个10000左右吧,即innodb_open_files设置为open_files_limit-10000)。

最后修改时间:2025-04-01 12:23:13
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
3人已赞赏
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论