记一次生产数据库"意外"重启的经历-天下标王
运维 数据库运维
在一个阳光明媚的下午,电脑右下角传来一片片邮件提醒,同时伴随着微信钉钉的震动,打开一看,应用各种出错,天兔告警,数据库服务器内存爆红,MySql 数据库实例挂掉了。

[[251734]]

 前言

在一个阳光明媚的下午,电脑右下角传来一片片邮件提醒,同时伴随着微信钉钉的震动,打开一看,应用各种出错,天兔告警,数据库服务器内存爆红,MySql 数据库实例挂掉了。

排查

先交代一下数据库版本:   

  1. mysql> status  
  2.     --------------  
  3.     mysql  Ver 14.14 Distrib 5.7.22-22, for Linux (x86_64) using  6.2  
  4.     Connection id:          59568  
  5.     Current database:  
  6.     Current user:           root@localhost  
  7.     SSL:                    Not in use  
  8.     Current pager:          stdout  
  9.     Using outfile:          ''  
  10.     Using delimiter:        ;  
  11.     Server version:         5.7.22-22-log Percona Server (GPL), Release 22, Revision f62d93c  
  12.     Protocol version:       10 

崩溃故障排除绝不是一项有趣的任务,特别是如果MySQL没有报告崩溃的原因。例如,当MySQL内存不足时。

数据库邮件告警提醒发来的消息:   

  1. Type: mysql  
  2.    Tags: 生产主库  
  3.    Host: 172.16.1.66:3306  
  4.    Level: critical  
  5.    Item: connect  
  6.    Value: down  
  7.    Message: mysql server down 

登录 Grafana 监控面板,数据库连接在哪个时间段曾有幅度的增长。

顺手检查一下之前的服务器邮件监控告警记录,上一个时间点,内存占用率99%,这说明了数据库连接的幅度增长,可能是压垮服务器的最后一根稻草。

其实导致OOM的直接原因并不复杂,就是因为服务器内存不足,内核需要回收内存,回收内存就是kill掉服务器上使用内存最多的程序,而MySQL服务可能就是使用内存最多,所以就OOM了。 

  1. Type: os  
  2.   Tags: 66数据库  
  3.   Host: 172.16.1.66:  
  4.   Level: critical  
  5.   Item: memory  
  6.   Value: 99%  
  7.   Message: too more memory usage 

查看系统日志

我们带着这个疑问来排查一下日志: 

  1. # 查看日志  
  2.   tail -500f  /var/log/messages  
  3.   # 以下是 oom-killer  
  4.   Nov 27 14:55:48 itstyledb1 kernel: mysqld invoked oom-killer: gfp_mask=0x201daorder=0oom_score_adj=0  
  5.   Nov 27 14:55:48 itstyledb1 kernel: mysqld cpuset=/ mems_allowed=0-1  
  6.   Nov 27 14:55:48 itstyledb1 kernel: CPU: 2 PID: 895 Comm: mysqld Kdump: loaded Not tainted 3.10.0-862.3.2.el7.x86_64 #1  
  7.   Nov 27 14:55:48 itstyledb1 kernel: Hardware name: Huawei RH1288 V3/BC11HGSC0, BIOS 3.22 05/16/2016  
  8.   Nov 27 14:55:48 itstyledb1 kernel: Call Trace: 

小伙伴们继续往下看: 

  1. 0 pages HighMem/MovableOnly  
  2.   Nov 27 14:55:48 itstyledb1 kernel: 291281 pages reserved  
  3.   Nov 27 14:55:48 itstyledb1 kernel: [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name  
  4.   Nov 27 14:55:48 itstyledb1 kernel: [  468]     0   468    28271     4326      62       55             0 systemd-journal  
  5.   Nov 27 14:55:48 itstyledb1 kernel: [  490]     0   490    11492        2      24      553         -1000 systemd-udevd  
  6.   Nov 27 14:55:48 itstyledb1 kernel: [  787]     0   787    13877       18      27       96         -1000 auditd  
  7.   Nov 27 14:55:48 itstyledb1 kernel: [  810]    81   810    14552       81      34       89          -900 dbus-daemon  
  8.   Nov 27 14:55:48 itstyledb1 kernel: [  815]     0   815    55956        1      60      466             0 abrtd  
  9.   Nov 27 14:55:48 itstyledb1 kernel: [  816]     0   816    55327        9      64      346             0 abrt-watch-log  
  10.   Nov 27 14:55:48 itstyledb1 kernel: [  818]     0   818   121607      220      90      495             0 NetworkManager  
  11.   Nov 27 14:55:48 itstyledb1 kernel: [  822]     0   822     5415       49      16       33             0 irqbalance  
  12.   Nov 27 14:55:48 itstyledb1 kernel: [  823]   997   823   134634       97      60     1306             0 polkitd  
  13.   Nov 27 14:55:48 itstyledb1 kernel: [  825]     0   825     6594       42      20       41             0 systemd-logind  
  14.   Nov 27 14:55:48 itstyledb1 kernel: [  830]     0   830    31578       28      21      139             0 crond  
  15.   Nov 27 14:55:48 itstyledb1 kernel: [  839]     0   839    27522        2      10       31             0 agetty  
  16.   Nov 27 14:55:48 itstyledb1 kernel: [ 1142]     0  1142   143454      114      97     2672             0 tuned  
  17.   Nov 27 14:55:48 itstyledb1 kernel: [ 1144]     0  1144    28203       11      59      246         -1000 sshd  
  18.   Nov 27 14:55:48 itstyledb1 kernel: [ 1145]     0  1145    97438      694     103      328             0 rsyslogd  
  19.   Nov 27 14:55:48 itstyledb1 kernel: [ 1369]     0  1369    22526       20      44      256             0 master  
  20.   Nov 27 14:55:48 itstyledb1 kernel: [ 1371]    89  1371    22596       32      46      251             0 qmgr  
  21.   Nov 27 14:55:48 itstyledb1 kernel: [ 5140]     0  5140     5102     1617      15      239             0 mysqld_exporter  
  22.   Nov 27 14:55:48 itstyledb1 kernel: [ 9430]     0  9430    55966      378      62      790             0 snmpd  
  23.   Nov 27 14:55:48 itstyledb1 kernel: [30320]    27 30320 22951376 13928375   43437  8163662             0 mysqld  
  24.   Nov 27 14:55:48 itstyledb1 kernel: [  688]    89   688    22552      271      46        0             0 pickup  
  25.   Nov 27 14:55:48 itstyledb1 kernel: Out of memory: Kill process 30320 (mysqld) score 984 or sacrifice child  
  26.   Nov 27 14:55:48 itstyledb1 kernel: Killed process 30320 (mysqld) total-vm:91805504kB, anon-rss:55713500kB, file-rss:0kB, shmem-rss:0kB  
  27.   Nov 27 14:56:00 itstyledb1 systemd: mysqld.service: main process exited, code=killedstatus=9/KILL  
  28.   Nov 27 14:56:00 itstyledb1 systemd: Unit mysqld.service entered failed state.  
  29.   Nov 27 14:56:00 itstyledb1 systemd: mysqld.service failed.  
  30.   Nov 27 14:56:00 itstyledb1 systemd: mysqld.service holdoff time over, scheduling restart.  
  31.   Nov 27 14:56:01 itstyledb1 systemd: Starting MySQL Server... 

当out of memory发生时,outofmemory函数会选择一个内核认为犯有分配过多内存 “罪行”的进程,并杀死该进程。显然 Mysql 就是哪个“罪人”。

随后 MySql 会自动重启。重启以后,内存是下来了,但是临近下班的时候,差不多又又又占满了。 

  1. [root@itstyledb1 ~]# free -m  
  2.                total        used        free      shared  buff/cache   available  
  3.  Mem:          55803       54976         241          10         585         349  
  4.  Swap:         32064       25036        7028 

找到MySql进程,执行以下top -p pid,内存使用52.4g 

  1. PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND  
  2.   935 mysql     20   0   79.7g  52.4g   7336 S   0.3 96.1 255:44.76 mysqld 

计算内存使用

1)查看MySQL全局占用多少内存

 

  1. SELECT (@@innodb_buffer_pool_size  
  2. +@@innodb_log_buffer_size  
  3. +@@key_buffer_size) / 1024 /1024 AS MEMORY_MB; 

查询结果为:   

  1. +----------------+  
  2.    | MEMORY_MB      |  
  3.    +----------------+  
  4.    | 20512.00000000 |  
  5.    +----------------+ 

2)查看performance_schema占用多少内存 

  1. SELECT SUBSTRING_INDEX(event_name,'/',2) AS  
  2.          code_area, sys.format_bytes(SUM(current_alloc))  
  3.          AS current_alloc  
  4.          FROM sys.x$memory_global_by_current_bytes  
  5.          GROUP BY SUBSTRING_INDEX(event_name,'/',2)  
  6.          ORDER BY SUM(current_alloc) DESC; 

查询结果为:   

  1. +---------------------------+---------------+  
  2.     | code_area                 | current_alloc |  
  3.     +---------------------------+---------------+  
  4.     | memory/performance_schema | 349.80 MiB    |  
  5.     +---------------------------+---------------+ 

3)查看每个线程占用多少内存   

  1. SELECT ( ( @@read_buffer_size  
  2.    + @@read_rnd_buffer_size  
  3.    + @@sort_buffer_size  
  4.    + @@join_buffer_size  
  5.    + @@binlog_cache_size  
  6.    + @@thread_stack  
  7.    + @@max_allowed_packet  
  8.    + @@net_buffer_length )  
  9.    ) / (1024*1024) AS MEMORY_MB; 

查询结果为: 

  1. +-----------+  
  2.   | MEMORY_MB |  
  3.   +-----------+  
  4.   |   87.5156 |  
  5.   +-----------+ 

查看当前线程   

  1. show full processlist 

最终结果为:   

  1. +-----------+  
  2.     | MEMORY_MB |  
  3.     +-----------+  
  4.     | 87.5156*37|  
  5.     +-----------+ 

4)查看 memory 存储引擎占用多少内存   

  1. SELECT SUM(max_data_length)/1024/1024 AS MEMORY_MB FROM information_schema.tables WHERE ENGINE='memory'

查询结果为:

 

  1. +---------------+  
  2. | MEMORY_MB     |  
  3. +---------------+  
  4. | 3857.37713909 |  
  5. +---------------+ 

以上四项加起来差不多也就27975MB,差不错28G的样子,但是 MySql 进程显示占用了52.4G,那么剩下24.4G去哪了?

线程池

此线程池非彼连接池,其实两者是有很大区别的,连接池一般在客户端设置,而线程池是在DB服务器上配置;另外连接池可以取到避免了连接频繁创建和销毁,但是无法取到控制MySQL活动线程数的目标,在高并发场景下,无法取到保护DB的作用。比较好的方式是将连接池和线程池结合起来使用。

关于线程池的一些参数:   

  1. mysql> show variables like 'thread%';  
  2.    +-------------------------------+---------------------------+  
  3.    | Variable_name                 | Value                     |  
  4.    +-------------------------------+---------------------------+  
  5.    | thread_handling               | one-thread-per-connection |  
  6.    | thread_pool_high_prio_mode    | transactions              |  
  7.    | thread_pool_high_prio_tickets | 4294967295                |  
  8.    | thread_pool_idle_timeout      | 60                        |  
  9.    | thread_pool_max_threads       | 100000                    |  
  10.    | thread_pool_oversubscribe     | 3                         |  
  11.    | thread_pool_size              | 12                        |  
  12.    | thread_pool_stall_limit       | 500                       |  
  13.    +-------------------------------+---------------------------+ 

thread_handling:

该参数是配置线程模型,默认情况是one-thread-per-connection,也就是不启用线程池。将该参数设置为pool-of-threads即启用了线程池。

threadpoolsize:

该参数是设置线程池的Group的数量,默认为系统CPU的个数,充分利用CPU资源。

threadpooloversubscribe:

该参数设置group中的最大线程数,每个group的最大线程数为threadpooloversubscribe+1,注意listener线程不包含在内。

threadpoolhighpriomode:

高优先级队列的控制参数,有三个值(transactions/statements/none),默认是transactions,三个值的含义如下:

  •  transactions:对于已经启动事务的语句放到高优先级队列中,不过还取决于后面的threadpoolhighpriotickets参数
  •  statements:这个模式所有的语句都会放到高优先级队列中,不会使用到低优先级队列
  •  none:这个模式不使用高优先级队列

threadpoolhighpriotickets:

该参数控制每个连接最多语序多少次被放入高优先级队列中,默认为4294967295,注意这个参数只有在threadpoolhighpriomode为transactions的时候才有效果。

threadpoolidle_timeout:

worker线程最大空闲时间,默认为60秒,超过限制后会退出。

threadpoolmax_threads:

该参数用来限制线程池最大的线程数,超过该限制后将无法再创建更多的线程,默认为100000。

threadpoolstall_limit:

该参数设置timer线程的检测group是否异常的时间间隔,默认为500ms。

最终配置如下:   

  1. #thread pool  
  2.    thread_handling=pool-of-threads  
  3.    #Group的数量,默认为系统CPU的个数,充分利用CPU资源  
  4.    thread_pool_size=24  
  5.    #每个group的最大线程数为thread_pool_oversubscribe+1  
  6.    thread_pool_oversubscribe=3  
  7.    performance_schema=off  
  8.    #extra connection,防止线程池满的情况下无法登录MySQL  
  9.    extra_max_connections = 8  
  10.    extra_port = 33333 

备注:线程池在Percona,MariaDB,Oracle MySQL企业版中提供,Oracle MySQL社区版并不提供。

线程池貌似并不会直接导致内存不回收,网上有说同时开启Thread pool和PS会出现内存泄露,但是 目前Percona server 5.7.21-20+版本已经修复了这个问题,显然是不存在的。

慢查询

由于是生产环境,这个问题拖得时间有点长,那么慢查询会不会影响内存使用问题呢?带着这个问题,查看了慢查询后台列表,在数据库奔溃的前一个时间段,的确有不少慢查询语句。但是这并不能在一定程度上说明问题,由于服务器的 MySql 服务在杀死之前,内存已经见底,此时连接数并不多,也就三四十来个左右,大多处于休眠状态,并且此时已经占用了大部分的Swap空间。也就是说,在资源有限的情况下必定会出现不少慢查询语句。

小结

其实这个"意外"一点也不意外,其实已经发生了多次了。但是还是做个小结吧,因为最终没有确认问题出现在哪里,所以还是发布了吧,万一有专业的DBA遇到类似的问题还可以小小的解惑一下。

 

责任编辑:庞桂玉 来源: ITPUB
相关推荐

2019-08-19 01:34:38

数据库SQL数据库优化

2019-11-18 13:42:55

MySQL数据库迁移

2019-11-22 08:05:01

数据库mysql分区

2019-12-12 10:38:10

mysql数据库nnodb

2019-07-25 08:30:58

数据库服务器故障

2019-09-27 17:24:26

数据库优化sql

2019-12-16 07:18:42

数据库SQL代码

2019-09-05 09:17:37

MySQL数据库线程

2018-07-18 15:37:24

数据库DB2故障处理

2019-09-08 17:52:10

数据库log file sy等待事件

2019-12-02 08:09:57

境数据库连接超时自动回收

2021-03-01 06:14:50

环境高并发延迟

2020-11-03 07:34:12

Kafka后端工程师

2022-06-01 06:17:42

微服务Kafka

2017-10-27 09:01:26

Oracle存储管理

2020-09-25 07:57:42

生产事故系统

2021-01-12 07:57:36

MySQLBinlog故障处理

2019-12-27 10:43:48

磁盘数据库死锁

2013-04-01 10:27:37

程序员失业

2013-01-17 10:31:13

JavaScriptWeb开发firebug
系统运维
7318内容
全部话题

相关专题 更多

2024年第十九届中国企业年终评选榜单揭晓
2024年第十九届中国企业年终评选榜单揭晓
如何发挥数据的最大力量?
如何发挥数据的最大力量?
2024-09-11 10:06:01
戴尔与AMD携手发布新一代服务器解决方案
戴尔与AMD携手发布新一代服务器解决方案
2024-12-24 16:34:07
我收藏的内容
点赞
收藏
分享

51CTO技术栈公众号

业务
速览
在线客服
媒体
51CTO CIOAge HC3i
社区
51CTO博客 鸿蒙开发者社区 AI.x社区
教育
51CTO学堂 精培 企业培训 CTO训练营

相关内容推荐

杭州实力强的销售行业网站优化求推荐传统行业网站优化清远网站排名优化价格佛山百度网站快速优化网站排名优化ク問宙斯典范谭坊网站优化eos网站优化巩义网站seo优化怎么选大兴网站优化推广哪家好汉渠县网站优化永州网站排名优化金乡谷歌网站优化黄山网站优化公司找哪家网站第4页如何优化佛山专业网站优化方式工农区网站seo优化排名新乡知名网站优化网站排名优化唯独金手指22喜马拉雅网站如何进行优化济南哪家网站优化公司好松原网站优化报价天台宁波网站优化网站优化怎么抓蜘蛛式分析网站推广和优化的原因经开区网站优化排名网站设计制作优化沙田鞋网站优化咨询平谷网站优化济南优化网站怎么样景点网站优化价格移动网站优化外包如何优化网站欧云速捷可以网站优化服务商争涌大王网站推广与优化青海律师网站优化网站自然优化排名方式宁波好口碑的网站优化郑州网站空间优化网站优化总部网站打开速度慢后台怎么优化许昌网站关键词优化排名推广网站页面优化 meta贵阳网站专题优化襄县网站优化公司青海网站排名优化报价广州网站建设网站优化推广深圳互联网网站优化广告网站知识优化宜兴网站关键词优化多少钱鸡西网站关键词优化排名日照模板网站优化公司网站优化软件价格网站营业执照转移对优化影响宁波江东区网站优化价格网站性能优化论文网站排名优化的选内江企业网站优化公司网站seo优化一年多少钱优化网站推广哪个好湖州信阳营销型网站优化系统移动网站可以优化关键词优化排名网站易速达三灶网站优化多少钱南山网站优化方法网站优化多少钱怎么收费网站优化外包岗位成都网站运营优化系统黄山企业网站优化哪家快深圳独立外贸网站优化哪个好汤阴县网站优化企业淮安市网站关键词优化价格网站优化有何作用上海如何进行网站关键词优化网站目标关键词优化前景网站图片标签优化的策略无锡网站优化设计移动网站可以优化博望网站优化优化网站排名须知易速达德州网站排名优化南通百度网站优化排名宁波江东区网站优化价格黄江网站优化推广鸡泽县网站seo优化排名好的珠宝行业网站优化多少钱南通网站优化驭明四川网站优化工具视频网站优化要注意什么网店推广书香满屋网站优化行业竞争网站优化新乡优化网站排名找哪家上海全过程网站搭建优化清远网站排名优化价格偃师网站优化排名绥德县网站seo优化排名长宁区百度网站优化定制临猗网站优化好处模板网站下载好优化吗网站排名优化忄在宙r斯专治网站排名优化昂扬易速达竞争对手网站优化分析海宁市网站seo优化排名华容区网站排名优化要多少钱新乡网站建设优化哪家靠谱四川广元网站优化建设石家庄卫浴行业网站优化推广优点安庆网站优化哪家有实力优化域名网站视频开关网站seo优化平台毕设网站优化设计总结西宁优化网站seo是什么网站结构优化方案总结武汉网站优化企业长丰网站优化广东网站优化推广服务是根本沁阳关键词网站优化新乡知名网站优化公司推荐营销型网站如何优化网站seo优化互点的软件松桃县网站优化营销网站优化排名首推云速捷如何进行网站内容的优化网站功能结构优化河南网站目标关键词优化聊城品牌网站优化广州网站seo优化哪家好黄浦网站优化哪家好东莞五金网站优化都有哪些雷山网站优化推广公司海南省网站优化加盟专业的婚纱摄影网站优化方法宿迁媒体网站优化优势火车购票网站优化网站建立优化技巧深圳网站搜索优化三穗网站优化福建优化网站营销的基本策略震泽网站优化网站优化案例大全萍乡网站优化科技有限公司镇安县网站seo优化排名郑州新站seo网站优化无锡快速优化网站番禺网站seo推广优化技巧房山外贸网站优化建设福建给网站优化哪个平台好优化排名网站喜欢易速达神农架网站优化推广网站搜索优化首选金苹果亠大数据网站怎么做优化做移动网站优化首页永仁百度网站优化费用怎么优化好的网站网站优化代码实例优化效果差的网站个人如何做网站优化需要多少钱湖州安吉优化网站推广青海网站排名优化怎么弄江门涂料网站seo优化咸宁公司网站优化外包价格网站优化第一步做什么阜南县网站优化焦作知名网站优化公司哪家好政府网站优化建议中卫网站seo优化seo优化网站标题的重要性三明网站seo优化报价惠州网站关键词优化苏州网站优化排名系统佛山南海网站seo优化阳江优化网站报价安康网站优化外包如何在网站优化成功案例好的电商网站优化费用做网站优化服务成都网站优化的要点都有哪些呢兴化网站搜索优化方案政务网站建设优化优化网站排名问云速捷认可河南设计网站优化湖北网站seo优化价格优化网站排名舒心火4星完美宁夏银川网站优化推广南海网站优化新网站建设后怎么优化网站seo敏感词的优化词有实力的网站优化如何把网站优化方案雨花台区网站优化潍坊品牌网站优化公司洛阳伊滨网站优化seo行业竞争网站优化网站SEO优化排名流程中山专业网站优化市南网站优化公司瑞金市网站优化推广衢州网站优化策略给网站做优化怎么选取关键词金山区公司官方网站优化平台吉林专业seo网站关键词优化

合作伙伴

天下标王

龙岗网络公司
深圳网站优化
龙岗网站建设
坪山网站建设
百度标王推广
天下网标王
SEO优化按天计费
SEO按天计费系统