MySQL 5.7 OOM问题诊断——就是这么简单

Inside君最近把金庸先生的笑傲江湖重看了三遍,感慨良多。很多工作、管理、生活、学习上的问题都能在其中一窥究竟,而那是年轻时所不能体会的一种感悟。比如下面风清扬的这段话:

风清扬又道:“单以武学而论,这些魔教长老们也不能说真正已窥上乘武学之门。他们不懂得,招数是死的,发招之人却是活的。死招数破得再妙,遇上了活招数,免不了缚手缚脚,只有任人屠戮。这个‘活’字,你要牢牢记住了。学招时要活学,使招时要活使。倘若拘泥不化,便练熟了几千万手绝招,遇上了真正高手,终究还是给人家破得干干净净。”

今天,来谈谈MySQLOOMout of memory)问题诊断。之前,这类问题的定位对于普通用户来说并不怎么简单。但是在MySQL 5.7中,OOM问题的定位变得极其容易。还没掌握的小伙伴赶快来看下吧。通常来说,发生OOM时可在系统日志找到类似的日志提示:

MySQL 5.7 OOM问题诊断——就是这么简单-MySQL社区 Inside MySQL Group

MySQL 5.7的库performance_schema新增了以下这几张表,用于从各维度查看内存的消耗:

  • memory_summary_by_account_by_event_name
  • memory_summary_by_host_by_event_name
  • memory_summary_by_thread_by_event_name
  • memory_summary_by_user_by_event_name
  • memory_summary_global_by_event_name

简单来说,就是可以根据用户、主机、线程、账号、全局的维度对内存进行监控。同时库sys也就这些表做了进一步的格式化,可以使得用户非常容易的观察到每个对象的内存开销:

mysql> select event_name,current_alloc
-> from memory_global_by_current_bytes limit 10;
+------------------------------------------------------------------------------+---------------+
| event_name | current_alloc |
+------------------------------------------------------------------------------+---------------+
| memory/performance_schema/events_statements_history_long | 13.66 MiB |
| memory/performance_schema/events_statements_history_long.sqltext | 9.77 MiB |
| memory/performance_schema/events_statements_history_long.tokens | 9.77 MiB |
| memory/performance_schema/events_statements_summary_by_digest.tokens | 9.77 MiB |
| memory/performance_schema/table_handles | 9.00 MiB |
| memory/performance_schema/events_statements_summary_by_thread_by_event_name | 8.80 MiB |
| memory/performance_schema/memory_summary_by_thread_by_event_name | 5.62 MiB |
| memory/performance_schema/events_statements_summary_by_digest | 4.88 MiB |
| memory/performance_schema/events_statements_summary_by_user_by_event_name | 4.40 MiB |
| memory/performance_schema/events_statements_summary_by_account_by_event_name | 4.40 MiB |
+------------------------------------------------------------------------------+---------------+
10 rows in set (0.00 sec)

细心的同学可能会发现,默认情况下performance_schema只对performance_schema进行了内存开销的统计。但是在对OOM进行诊断时,需要对所有可能的对象进行内存监控。因此,还需要做下面的设置:

mysql> update performance_schema.setup_instruments
-> set enabled = 'yes' where name like 'memory%';
Query OK, 310 rows affected (0.00 sec)
Rows matched: 380  Changed: 310  Warnings: 0

mysql> select * from performance_schema.setup_instruments where name like 'memory%innodb%' limit 5;
+-------------------------------------------+---------+-------+
| NAME | ENABLED | TIMED |
+-------------------------------------------+---------+-------+
| memory/innodb/adaptive hash index | YES | NO |
| memory/innodb/buf_buf_pool | YES | NO |
| memory/innodb/dict_stats_bg_recalc_pool_t | YES | NO |
| memory/innodb/dict_stats_index_map_t | YES | NO |
| memory/innodb/dict_stats_n_diff_on_level | YES | NO |
+-------------------------------------------+---------+-------+
5 rows in set (0.00 sec)

但是这种在线打开内存统计的方法仅对之后新增的内存对象有效:

mysql> select event_name,current_alloc from memory_global_by_current_bytes
-> where event_name like '%innodb%';
+------------------------+---------------+
| event_name | current_alloc |
+------------------------+---------------+
| memory/innodb/mem0mem | 36.52 KiB |
| memory/innodb/trx0undo | 704 bytes |
| memory/innodb/btr0pcur | 271 bytes |
+------------------------+---------------+
3 rows in set (0.01 sec)

如想要对全局生命周期中的对象进行内存统计,必须在配置文件中进行设置,然后重启:

[mysqld]
performance-schema-instrument='memory/%=COUNTED'

mysql> select event_name,current_alloc from memory_global_by_current_bytes limit 5;
+----------------------------+---------------+
| event_name | current_alloc |
+----------------------------+---------------+
| memory/innodb/os0file | 1.42 GiB |
| memory/innodb/buf_buf_pool | 1.05 GiB |
| memory/innodb/os0event | 51.15 MiB |
| memory/innodb/hash0hash | 41.44 MiB |
| memory/innodb/log0log | 32.01 MiB |
+----------------------------+---------------+
5 rows in set (0.00 sec)

通过上面的结果,有小伙伴是不是已经发现可疑的内存使用了呢?memory/innodb/os0file这个对象使用了1.42G内存,而整个数据库实例的Buffer Pool只有1.05G。那么这时就可以去bugs.mysql.com上去搜索下。果不其然,是一个官方bug,并已在5.7.14修复。而通过类似方法Inside君已经定位了5起OOM问题。当然,这里Inside君只是抛出了一个思路,活学活用,才能达到无招胜有招的至臻境界。

PS:Inside君亲授的上海MySQL线下周末版将于11月12日开课,15个名额,目前仅剩最后6个名额,先到先得。课纲较第1、2期做了大幅调整,新增了MySQL 8.0的相关特性、新增了大量实战操作。还在学习MySQL 5.1、5.5?还在学习MyISAM?还在被那些所谓的老师忽悠?快来报名参加最好的MySQL数据库培训。报名咨询,微信:82946772

发表评论

坐等沙发
相关文章
IMG社区MySQL技术沙龙南京站圆满结束
IMG社区MySQL技术沙龙南京站圆满结束
改朝换代:MySQL Group Replication
改朝换代:MySQL Group Replication
数据库行业的朋友圈内幕,不知道就没法混了
数据库行业的朋友圈内幕,不知道就没法…
Inside MySQL Group社区启用新LOGO
Inside MySQL Group社区启用新LOGO
MySQL 5.7 semi-sync 1024 bug 修复
MySQL 5.7 semi-sync 1024 bug 修复
MySQL超越Oracle了?
MySQL超越Oracle了?
Oracle MySQL ACE. Author of Inside MySQL and MySQL Core Series. Great at MySQL performance tuning、troubleshooting、systems availability and scalability、capacity planning, etc.

一触即发,2017年,数据库世界的诸神之战