作者:汤薇
爱可生南区 DBA 组成员,次要负责 MySQL 的日常保护及故障解决。善于多种数据库的运维教训及故障调优。
本文起源:原创投稿
* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。
一、背景形容
最近应用 xtrabackup 工具对 mysql 实例进行备份时,因为实例的 ibd 文件过多,而备份用户 的 open files 参数设置的值太小,在备份实例时关上的文件数量超过了备份用户容许关上的文件 数量限度,导致备份失败,其报错如下:
220330 08:28:47 >> log scanned up to (328701072168)
InnoDB: Operating system error number 24 in a file operation.
InnoDB: Error number 24 means 'Too many open files'
InnoDB: Some operating system error numbers are described at
http://dev.mysql.com/doc/refman/5.7/en/operating-system-error-codes.html
InnoDB: File ./stage/ts_cg_inteltaxtochanges #P#P_20220322.ibd: 'open' returned OS
error 124. Cannot continue operation
InnoDB: Cannot continue operation.
二、模仿故障场景
1、环境阐明
mysql 版本:v5.7.35
xtrabackup 版本:v2.4.24
2、查看 open files 的已知参数值
(1)操作系统以后的 open files 数量
[root@test ~]# ulimit -a
core file size (blocks, -c) 0
...
open files (-n) 1024
...
(2)mysql 实例配置文件 my.cnf 的 innodb_file_per_table、open_files_limit 参数值
[root@test ~]# less /opt/mysql/etc/3306/my.cnf |grep innodb_file_per_table
innodb_file_per_table = 1
[root@test ~]# less /opt/mysql/etc/3306/my.cnf |grep open_files_limit
open_files_limit = 20000
(3)备份用户 actiontech-mysql 在 /etc/security/limits.d 中的配置文件的 open files 的限度
[root@test ~]# cd /etc/security/limits.d
[root@test limits.d]# cat actiontech-mysql.conf
actiontech-mysql soft nofile 10240
actiontech-mysql hard nofile 10240
actiontech-mysql soft nproc 65535
actiontech-mysql hard nproc 65535
[root@test limits.d]# su -s $(which bash) actiontech-mysql
bash-4.2$ ulimit -a
core file size (blocks, -c) 0
...
open files (-n) 10240
...
3、应用 sysbench 生成大量数据表
[root@test ~]# /usr/share/sysbench/oltp_read_write.lua --table-size=1000 --tables=12000 --mysql-user=root --mysql-password=1 --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-db=testdb --threads=250 --time=60 --report-interval=3 --skiptrx=on --mysql-ignore-errors=1062 prepare
4、模仿在 root 用户与非 root 用户下备份的报错状况
(1)在非 root 用户 actiontech-mysql 下执行备份命令,复现报错景象
[root@test ~]# su -s $(which bash) actiontech-mysql
bash-4.2$ xtrabackup --defaults-file=/opt/mysql/etc/3306/my.cnf --user=root --
password=1 --socket=/opt/mysql/data/3306/mysqld.sock --backup --target-dir=/opt/mysql/backup/3306
xtrabackup: recognized server arguments: --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:autoextend --
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=20000
...
xtrabackup: open files limit requested 20000, set to 10240
...
220413 13:58:50 >> log scanned up to (6550086912)
InnoDB: Operating system error number 24 in a file operation.
InnoDB: Error number 24 means 'Too many open files'
InnoDB: Some operating system error numbers are described at
http://dev.mysql.com/doc/refman/5.7/en/operating-system-error-codes.ht ml
InnoDB: File ./testdb/sbtest4576.ibd: 'open' returned OS error 124. Cannot
continue operation
InnoDB: Cannot continue operation.
(2)间接以 root 用户备份
前提:将 mysql 配置文件中的 open_files_limit 参数值改小(20000->10000),重启数据库失效
[root@test ~]# less /opt/mysql/etc/3306/my.cnf |grep open_files_limit
open_files_limit = 10000
[root@test ~]# systemctl start mysqld_3306
在 root 用户下进行备份,复现报错景象
[root@test ~]# xtrabackup --defaults-file=/opt/mysql/etc/3306/my.cnf --user=root
--password=1 --socket=/opt/mysql/data/3306/mysqld.sock --backup --targetdir=/opt/mysql/backup/3306
xtrabackup: recognized server arguments: --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:autoextend --
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=10000
...
xtrabackup: open files limit requested 10000, set to 10000
...
220413 14:42:33 >> log scanned up to (6550257170)
InnoDB: Operating system error number 24 in a file operation.
InnoDB: Error number 24 means 'Too many open files'
InnoDB: Some operating system error numbers are described at
http://dev.mysql.com/doc/refman/5.7/en/operating-system-error-codes.html
InnoDB: File ./testdb/sbtest10796.ibd: 'open' returned OS error 124. Cannot
continue operation
InnoDB: Cannot continue operation.
以上两种状况均已胜利复现故障现场。
三、故障剖析
首先咱们统计下目前数据库须要关上多少文件
[root@test ~]# find /opt/mysql/data/3306 -name "*.ibd" |wc -l
12945
依据以上统计结果显示,咱们已知实例的 open_files_limit 的运行参数值为 20000,且大于备份时须要关上的文件数量,那为什么还会报错呢?
看以下官网给出的阐明,意思是当你在非 root 用户下执行备份时,用户容许的 open files 须要比备份时关上的文件数量要多才能够,而在 root 用户下是没有限度的,因而并不会有此问题。
联合以上官网的阐明,咱们再来看看应用的非 root 用户备份过程中 open files limit 理论的取值是多少?
查看备份日志,确认过后 open files limit 理论设置的值
xtrabackup: open files limit requested 20000, set to 10240
查看备份过程理论应用的 open files 的值
bash-4.2$ ps -ef|grep xtrabackup
actiont+ 19732 19630 0 16:03 pts/1 00:00:00 xtrabackup --defaultsfile=/opt/mysql/etc/3306/my.cnf --user=root --password=x --
socket=/opt/mysql/data/3306/mysqld.sock --backup --targetdir=/opt/mysql/backup/3306
bash-4.2$ cat /proc/19732/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
...
Max open files 10240 10240 files
..
显然 open files limit 申请的值为 20000,获取的是 mysql 配置文件中的值,然而理论设置的值为备份用户容许的 open files 的值 10240,少于下面统计的以后须要关上的文件数量,所以导致备份失败。
咱们再来看看间接应用 root 用户备份过程中 open files limit 理论的取值是怎么的?
查看备份日志,确认过后 open files limit 理论设置的值
xtrabackup: open files limit requested 10000, set to 10000
查看备份过程理论应用的 open files 的值
[root@test 3306]# ps -ef|grep xtrabackup
root 20826 8965 3 16:18 pts/1 00:00:00 xtrabackup --defaultsfile=/opt/mysql/etc/3306/my.cnf --user=root --password=x --
socket=/opt/mysql/data/3306/mysqld.sock --backup --targetdir=/opt/mysql/backup/3306
[root@test 3306]# cat /proc/20826/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
...
Max open files 10000 10000 files
...
可看到 open files limit 申请的值为 10000,获取的是 mysql 配置文件中的值,理论设置的值也是 10000,没有变动。这阐明在 root 用户下,间接以 mysql 配置文件中的 open files limit 为 理论容许关上文件数量的限度。
四、总结
(1)在非 root 用户下应用 xtrabackup 备份时,用户的 open files 值须要大于备份时关上的文件数量。倡议设置的值比配置文件中的 open_files_limit 参数值大,确保备份用户的 open files 是够备份时关上的文件数量。可在 /etc/security/limits.d 下批改 nofile 的值永恒失效,也能够间接在用户下 ulimit -n 批改 open files 使其长期失效。
# 批改用户的 soft、hard 的 nofile 值永恒失效
* soft nofile 20000
* hard nofile 20000
# 或者登录到用户下 ulimit - n 长期失效
(2)在 root 用户下应用 xtrabackup 备份时,因为 root 用户默认对 open files 不做限度,这时须要确保配置文件中的 ope_files_limit 的运行值是满足需要的,其备份会间接以配置文件中的参数值来限度容许关上的文件数量。也能够间接命令行选项传递合乎需要的值,或间接在执行备份前设置 ulimit -n 20000 使 open files 长期失效。
# 1. 批改配置文件中的 open_files_limit 值
[mysqld]
open_files_limit=20000
# 2. 执行指定命令行选项传递
--open-files-limit=20000
# 3、在执行备份前设置 ulimit 值
ulimit -n 20000
(3)确保零碎中放弃关上的最大文件数。如果这个数字太小,Percona Xtrabackup 可能会独占零碎中关上的文件,导致其余过程尝试关上文件时失败。这可能会导致 MySQL 服务器解体,以及其余过程失败。
# 查看零碎的 file-max
[root@test ~]# cat /proc/sys/fs/file-max
379560
# 批改 file-max
[root@test ~]# sysctl -w fs.file-max=5000000
[root@test ~]# echo "fs.file-max=5000000" >> /etc/sysctl.conf
参考资料:https://www.percona.com/blog/…