一、背景描述

最近使用xtrabackup工具对mysql实例进行备份时,由于实例的ibd文件过多,而备份用户的openfiles参数设置的值太小,在备份实例时打开的文件数量超过了备份用户允许打开的文件数量限制,导致备份失败,其报错如下:

22033008:28:47logscannedupto(328701072168)InnoDB::Errornumber24means'Toomanyopenfiles'InnoDB:Someoperatingsystemerrornumbersaredescribedat:'open':Cannotcontinueoperation.
二、模拟故障场景1、环境说明

mysql版本:

xtrabackup版本:

2、查看openfiles的已知参数值

(1)操作系统当前的openfiles数量

[root@test~]less/opt/mysql/etc/3306/|grepinnodb_file_per_tableinnodb_file_per_table=1[root@test~]cd/etc/security/[root@]su-s$(whichbash)$ulimit-acorefilesize(blocks,-c)0openfiles(-n)10240
3、使用sysbench生成大量数据表
[root@test~]su-s$(whichbash)$xtrabackup--defaults-file=/opt/mysql/etc/3306/=root--password=1--socket=/opt/mysql/data/3306/=/opt/mysql/backup/3306xtrabackup:recognizedserverarguments:--server-id=1224415609--datadir=/opt/mysql/data/3306--log_bin=/opt/mysql/log/binlog/3306/mysql-bin--tmpdir=/opt/mysql/tmp/3306--innodb_log_group_home_dir=/opt/mysql/log/redolog/3306--innodb_buffer_pool_size=1G--innodb_data_file_path=ibdata1:1G:autoext--innodb_file_per_table=1--innodb_flush_log_at_trx_commit=1--innodb_flush_method=O_DIRECT--innodb_io_capacity=1000--innodb_log_buffer_size=64M--innodb_log_file_size=2G--innodb_log_files_in_group=2--innodb_max_dirty_pages_pct=60--innodb_undo_tablespaces=3--innodb_read_io_threads=8--innodb_write_io_threads=8--innodb_open_files=4096--open_files_limit=20000xtrabackup:openfileslimitrequested20000,setto1024022041313:58:50logscannedupto(6550086912)InnoDB::Errornumber24means'Toomanyopenfiles'InnoDB:Someoperatingsystemerrornumbersaredescribedat:'open':Cannotcontinueoperation.

(2)直接以root用户备份

前提:将mysql配置文件中的open_files_limit参数值改小(20000-10000),重启数据库生效

[root@test~]systemctlstartmysqld_3306

在root用户下进行备份,复现报错现象

[root@test~]find/opt/mysql/data/3306-name"*.ibd"|wc-l12945

根据以上统计结果显示,我们已知实例的open_files_limit的运行参数值为20000,且大于备份时需要打开的文件数量,那为什么还会报错呢?

看以下官方给出的说明,意思是当你在非root用户下执行备份时,用户允许的openfiles需要比备份时打开的文件数量要多才可以,而在root用户下是没有限制的,因此并不会有此问题。

结合以上官方的说明,我们再来看看使用的非root用户备份过程中openfileslimit实际的取值是多少?

查看备份日志,确认当时openfileslimit实际设置的值

xtrabackup:openfileslimitrequested20000,setto10240

查看备份进程实际使用的openfiles的值

$ps-ef|grepxtrabackupactiont+1973219630016:03pts/100:00:00xtrabackup--defaultsfile=/opt/mysql/etc/3306/=root--password=x--socket=/opt/mysql/data/3306/=/opt/mysql/backup/3306$cat/proc/19732/limitsLimitSoftLimitHardLimitUnitsMaxcputimeunlimitedunlimitedsecondsMaxopenfiles1024010240files..

显然openfileslimit请求的值为20000,获取的是mysql配置文件中的值,但是实际设置的值为备份用户允许的openfiles的值10240,少于上面统计的当前需要打开的文件数量,所以导致备份失败。

我们再来看看直接使用root用户备份过程中openfileslimit实际的取值是怎样的?

查看备份日志,确认当时openfileslimit实际设置的值

xtrabackup:openfileslimitrequested10000,setto10000

查看备份进程实际使用的openfiles的值

[root@test3306]cat/proc/20826/limitsLimitSoftLimitHardLimitUnitsMaxcputimeunlimitedunlimitedsecondsMaxopenfiles1000010000files

可看到openfileslimit请求的值为10000,获取的是mysql配置文件中的值,实际设置的值也是10000,没有变化。这说明在root用户下,直接以mysql配置文件中的openfileslimit为实际允许打开文件数量的限制。

四、总结

(1)在非root用户下使用xtrabackup备份时,用户的openfiles值需要大于备份时打开的文件数量。建议设置的值比配置文件中的open_files_limit参数值大,确保备份用户的openfiles是够备份时打开的文件数量。可在/etc/security/下修改nofile的值永久生效,也可以直接在用户下ulimit-n修改openfiles使其临时生效。

或者登录到用户下ulimit-n临时生效

(2)在root用户下使用xtrabackup备份时,因为root用户默认对openfiles不做限制,这时需要确保配置文件中的ope_files_limit的运行值是满足需求的,其备份会直接以配置文件中的参数值来限制允许打开的文件数量。也可以直接命令行选项传递符合需求的值,或直接在执行备份前设置ulimit-n20000使openfiles临时生效。

2.执行指定命令行选项传递--open-files-limit=20000查看系统的file-max[root@test~]修改file-max[root@test~]echo"=5000000"/etc/

参考资料: