某日凌晨收到db故障告警,上机器检查,mysql已经被myqld守护进程重新启动。检查/var/log/messages和最近的dmesg发现mysql进程是被oom干掉了。
信息大概摘录如下:
[13045702.638964] kthread invoked oom-killer: gfp_mask=0xd0, order=1, oomkilladj=0
[13045702.638969]
[13045702.638969] Call Trace: <ffffffff8014a331>{oom_kill_process+87}
[13045702.638977] <ffffffff8014a722>{out_of_memory+271} <ffffffff8013ce59>{autoremove_wake_function+0}
ERROR: Fatal error found, match ERROR-KEYWORD 'out_of_memory'
...
[13045702.716335] Out of Memory: Kill process 25795 (mysqld) score 1591671 and children.
ERROR: Fatal error found, match ERROR-KEYWORD 'Out of Memory'
[13045702.716359] Out of memory: Killed process 25795 (mysqld).
.....
[13045702.802080] Out of Memory: Kill process 1907 (mysqld) score 955002 and children.
ERROR: Fatal error found, match ERROR-KEYWORD 'Out of Memory'
[13045702.802102] Out of memory: Killed process 1907 (mysqld).
....
[13045762.203463] Out of Memory: Kill process 24544 (mysqld) score 341071 and children.
ERROR: Fatal error found, match ERROR-KEYWORD 'Out of Memory'
[13045762.203485] Out of memory: Killed process 24544 (mysqld).
[13045762.322333] sap1002 invoked oom-killer: gfp_mask=0x201d2, order=0, oomkilladj=0
.....
[13045762.479886] Out of Memory: Kill process 19530 (mysqldump) score 93607 and children.
ERROR: Fatal error found, match ERROR-KEYWORD 'Out of Memory'
[13045762.479907] Out of memory: Killed process 19530 (mysqldump).
由于内存不足,系统选择性的选择了耗用内存大的几个进程kill掉了。先kill了mysqld,最后才把mysqldump kill掉,这样有理由怀疑可能是因为mysqldump耗用了大量的内存导致的。
在这个db上,每天凌晨会使用mysqldump做单表备份并通过管道进行压缩。这个备份任务已经部署了超过1年多了。
查看了后台采集的OS性能数据,也可以发现在mysqldump启动直到备份结束,内存耗用会上升比较多,这样可以肯定是因为mysqldump耗用大量内存导致此次故障发生。
check备份使用的脚本,备份的逻辑大概如下:
1:show tables like 'xxx%' 获取需要备份的表名
2:mysqldump --uxx -pyy --skip-opt <dbname> <tablename> >> <bakfilename>
至此问题就比较清晰了,mysqldump由于未使用-q参数导致耗用内存过大而导致OOM现象发生。
对mysqldump -q参数的解释(取自man mysqldump)
? --quick, -q
This option is useful for dumping large tables. It forces mysqldump to retrieve rows for a table from the server a row at a time rather than retrieving the entire row set and buffering it in memory before writing it out.
这个选项被用来dump比较大的表。它强制mysqldump从服务器一行一行的获取数据而不是把获取所有行的数据在输出之前把它缓存到内存中。
以下是一个测试,可以看到-q 参数对内存耗用的影响:
1:不带-q参数
top输出如下:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20010 mysql 15 0 18.0g 17g 4496 S 10 56.6 2765:51 mysqld
27518 mysql 25 0 4227m 4.1g 1048 R 100 13.1 0:33.05 mysqldump
内存耗用超过4G
2:带-q参数
top输出如下:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20010 mysql 16 0 18.0g 17g 4496 S 84 56.6 2766:12 mysqld
27686 mysql 25 0 11628 1380 1052 R 98 0.0 0:23.20 mysqldump
内存耗用很小,只有几K
应对方案:
修改备份脚本,加上-q参数。
到此还没完,这个备份任务已经部署了超过1年了,为啥到最近才出现此故障呢?
对DB内的数据做了个统计,需要备份表从之前100M/day的数据量突然爆增到4G/day。知会研发跟进问题,最后发现是前端配置更改导致前端不断重试导致。
体会:
在很多时候,故障的发生是很多因素交织在一起才发生的。碰到问题需要更深一层考虑去探寻问题发生的根本原因。
相关阅读:
Linux下通过mysqldump备份MySQL数据库成sql文件 http://www.linuxidc.com/Linux/2013-02/79793.htm
Linux中使用mysqldump对MySQL数据库进行定时备份 http://www.linuxidc.com/Linux/2012-03/56063.htm
相关推荐
LNH_MySQL 12-mysqldump-master-data参数答疑详解.mp4
LNH_MySQL 02-mysqldump-master-data参数答疑详解.mp4
mysql数据库备份还原实战操作步骤-mysqldump备份还原
Linux运维-运维课程d4-MySQL备份与恢复(重点)-19-mysqldump全库级备份.mp4
通过已经备份的数据库文件对数据库进行恢复测试,并输出测试报告,本次测试对数据库的全量及增量备份进行恢复,并在恢复完成后验证数据是否正常,恢复时间是否与备份时间相一致。...
LNH_MySQL 03-mysqldump逻辑备份的工作原理.mp4
NULL 博文链接:https://navylee.iteye.com/blog/1146725
MySQL:使用mysqldump在Windows数据库定时备份-- mysqldump --opt --single-transaction=TRUE --user=%user% --password=%password% --host=%host% --protocol=tcp --port=%port% --default-character-set=%charSet%...
备份MySQL数据库为带删除表的格式,能够让该备份覆盖已有数据库而不需要手动删除原有数据库。 mysqldump -–add-drop-table -uusername -ppassword databasename > backupfile.sql 直接将MySQL数据库压缩备份 ...
MySQL掌握备份恢复工具mysqldump实践
包里面的文件:mysql、mysqldump 两个命令 mysqldump使用方法:可直接使用,备份数据库 使用方法:mysqldump --opt -u用户名 -p密码 -hIP地址 -P数据库端口 要备份的库 > 导入指定的sql里 示例:mysqldump --opt -u...
介绍mysql数据库,单表备份,整库备份。
delphi备份和还原MySql数据库.zip源码,可以自动备份或还原MysqL数据库,在该源码中可以修改你的数据库名和密码及路径,就可为你所用。祝下载使用者编程成功!
此mysqldump版本为5.6.12,内含详细使用方法,包括cmd的备份方式、java的备份方式
详解 linux mysqldump 导出数据库、数据、表结构 导出完整的数据库备份: mysqldump -h127.0.0.1 -P3306 -uroot -ppassword --add-locks -q dbname > dbname.sql 说明:–add-locks:导出过程中锁定表,完成后回解锁...
在不依赖mysqldump CLI的情况下,在Go中创建MYSQL转储。 简单的例子 package main import ( "database/sql" "fmt" "github.com/JamesStewy/go-mysqldump" _ "github.com/go-sql-driver/mysql" ) func main () {...
备份-MySQL-Ansible 使用Ansible备份Mysql 这很有趣,它将排除mysql数据库,仅备份对我们很重要的数据库ansible-playbook playbook.yml --extra-vars " host=localhost user=username pass=password db_host=...
│ │ 5_Mysqldump基于表备份.mp4 │ │ 6_MySQL全量恢复和日志增量恢复.mp4 │ │ 7_xtrabackup全量和增量备份恢复.mp4 │ │ 作业及答案.docx │ │ │ └─MySQL DBA堂命令-mha和备份恢复 │ mysql-master_05-18...
Mysql数据备份与mysqldump增量备份.pdf
mysql完整备份和增量备份脚本,本文档采用mysqldump 对数据库进行备份,mysqldump 是采用SQL级别的备份机制,它将数据表导成 SQL脚本文件,在不同的 MySQL 版本之间升级时相对比较合适,这也是最常用的备份方法,...