转载

MySQL OOM问题处理一则

一个游戏业务的mysql数据库,多台服务器上mysql服务被OOM,但OOM的原因是什么呢?
其实导致OOM的直接原因并不复杂,就是因为服务器内存不足,内核需要回收内存,回收内存就是kill掉服务器上使用内存最多的程序,而mysql服务是使用内存最多,所以就OOM了。

首先我们检查是什么原因导致内存不足,这台服务器物理内存为64G
# free -m
             total       used       free     shared    buffers     cached
Mem:         64375      57821       6553          0        554      16369
-/+ buffers/cache:      40897      23478
Swap:        16383          5      16378


被oom第一个怀疑的原因就是innodb_buffer_pool_size大小设置是否合理
141205 18:47:57 [Note] Plugin 'FEDERATED' is disabled.
141205 18:47:57 InnoDB: The InnoDB memory heap is disabled
141205 18:47:57 InnoDB: Mutexes and rw_locks use GCC atomic builtins
141205 18:47:57 InnoDB: Compressed tables use zlib 1.2.3
141205 18:47:57 InnoDB: Using Linux native AIO
141205 18:47:57 InnoDB: Initializing buffer pool, size = 58.0G
141205 18:48:04 InnoDB: Completed initialization of buffer pool
141205 18:48:04 InnoDB: highest supported file format is Barracuda.
从上面mysql启动的日志中,可以看到在14年mysql启动的时候,innodb_buffer_pool_size设置成了58G,一直到OOM,innodb_buffer_pool_size一直是58G
一台物理内存为64G的服务器,innodb_buffer_pool_size的这个设置确实有点大

另一个检查是vm.swappiness的设置
现在服务器上vm.swappiness设置为0,而RHEL/CentOS 6.4的内核从2.6.32-358这个版本以后,swappiness的行为就已经修改了,
最新的内核,建议把vm.swappiness设置1
# uname -r
2.6.32-431.el6.x86_64
这里我们系统是最新的内核


但是通过下面的分析,发现innodb_buffer_pool_size,vm.swappiness两个参数设置的不合理只是OOM中的潜在问题,并不是触发OOM的直接原因


可以通过show engine innodb status,查看一下mysql内存的使用情况
.....
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 63979913216; in additional pool allocated 0
Internal hash tables (constant factor + variable factor)
    Adaptive hash index 7893457408      (7887918656 + 5538752)
    Page hash           61625224 (buffer pool 0 only)
    Dictionary cache    247241428       (246498992 + 742436)
    File system         111712  (82672 + 29040)
    Lock system         154077792       (154061624 + 16168)
    Recovery system     0       (0 + 0)
Dictionary memory allocated 742436
Buffer pool size        3801087
Buffer pool size, bytes 62277009408  --Buffer Pool大小
Free buffers            3686413  --Buffer Pool中有多少个空白页
Database pages          112368   --Buffer Pool中使用了多少页
Old database pages      22365
........
这里可以发现Buffer pool中大部分页都是Free的,其实mysql服务并未直接分配到58G的内存。


通过sar -B,发现了大量的与SWAP内存的交换,而这个频繁交换的时间是每半小时发生一次
10:00:01 AM  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
10:10:01 AM  24472.34  13779.62  10542.81      0.88   8986.53   1547.25     42.00   1556.45     97.94
10:20:01 AM     24.55  11989.73  10669.42      0.14   4369.46    138.54      0.11    138.64    100.00
10:30:01 AM      1.29   8991.32   9832.53      0.01   3596.49     20.53      0.55     21.08    100.00
10:40:01 AM  24522.56  17124.60  11295.04      0.75   9649.33   1710.20     51.21   1666.83     94.63
10:50:01 AM      4.68   8691.01  10355.18      0.08   3934.04     21.22      0.11     21.33    100.00
11:00:01 AM      3.71  10738.47  10384.87      0.09   4017.96     94.24      0.28     94.47     99.96
11:10:02 AM  24924.74  14603.99  11129.07      0.86   9504.08   1751.06     40.43   1642.30     91.67
11:20:01 AM     11.95   8548.50  10206.84      0.11   3819.67     48.74      0.11     48.85    100.00
Average:      8944.00  11658.11  10479.06      0.40   5958.60    687.73     18.04    668.62     94.74


每半个小时的SWAP内存交换是什么引起的呢?
[root@tlbb3d_yd_mxy_120-132-43-203_sx ~]# crontab -l
00 05 * * * /bin/bash /home/databak/scripts/xtrabackup.sh FULL_BACKUP
*/30 * * * * /bin/bash /home/databak/scripts/xtrabackup.sh INCRE_BACKUP
00 03 * * * /bin/bash /home/databak/dbbbak.sh xxx


通过crontab 发现,这台服务器每半个小时使用xtrabackup对mysql做一次增备,
这个增备的起点是基于每天凌晨5点的全备进行的,也就意味着随着时间增备的数据量会越来越大,
备份时长也会越来越长,也就意味着系统资源会越来越紧张,以下也可以看到数据的增长情况
# du -sh *
2.4G    201602261030
2.5G    201602261100


很显然通过以上的分析我们需要做以下三件事情来解决mysql的OOM
1.将innodb_buffer_pool_size设置为48G
2.将vm.swappiness设置为1
3.调整增量备份时间(需要和业务平衡),拉长增量备份的间隔,降低系统的资源消耗



vm.swappiness参考:https://www.percona.com/blog/2014/04/28/oom-relation-vm-swappiness0-new-kernel/



正文到此结束
Loading...