MySQL table_open_cache 设置偏小导致 thread running 过高告警

业务进行 MySQL 性能压测,在压测过程中遇到 thread running 过高的告警,经过排查,cpu,io,内存,网络等监控指标并没有显著的异常,而抓取 processlist,发现大量 SQL 执行处于 opening tables 和 closing tables 状态,怀疑 table_open_cache 参数设置过小,调大了 table_open_cache 参数值之后,thread running 过高的问题恢复正常。

一、现象

  1. MySQL 版本 5.7.19
  2. MySQL 压测时 thread running 增长到 300 左右
  3. show processlist 显示大量 SQL 执行处于 opening tables 和 closing tables 状态
  4. 业务库中表的数量为 4000 左右
  5. MySQL 参数 table_open_cache 为 4096
  6. MySQL 状态指标 Open_tables 为 4096,Opened_tables 在不断的快速增长

二、原因调查

processlist 中 大量 SQL 处于 opening tables 和 closing tables,并且 table_open_cache 缓存被打满(Open_tables 为 4096,并且 Opened_tables 在不断快速增长),基本可以判断是 table_open_cache 参数设置偏小了,调大 table_open_cache 值,恢复正常。

有一个疑问,业务表只有 4000 左右,table_open_cache 设置为 4096,已经大于业务表的数量,为什么仍然不够?造成这一现象的原因是业务 SQL 使用了 join,即一个 SQL 涉及到了多张表,并发执行时,就会导致 Open_tables 值超过实际表数量的情况,MySQL官方文档有这样一段描述:

table_open_cache is related to max_connections. For example, for 200 concurrent running connections, specify a table cache size of at least 200 * N, where N is the maximum number of tables per join in any of the queries which you execute. You must also reserve some extra file descriptors for temporary tables and files.

三、解决方案

调大 table_open_cache 参数值,减少业务表频繁打开和关闭。至于调整到多少合适,查看 MySQL 状态参数 Open_tables 和 Opened_tables,当 Open_tables 接近 table_open_cache,并且 Opened_tables 不会快速增加时,那么此时的 table_open_cache 值就是一个比较合适的值。

table_open_cache 也不是越大越好,毕竟在表多的时候,也需要更多的内存消耗。

除了 table_open_cache 之外,还有两个参数,可以一起关注一下:

  • table_open_cache_instances
  • table_definition_cache

如果 table_open_cache_instances 设置过小,在高并发场景下,可能导致 MySQL 内部线程严重的
mutex 竞争。

参考:

https://www.cnblogs.com/CtripDBA/p/10304856.html

https://dev.mysql.com/doc/refman/5.7/en/optimize-multi-tables.html

文章评论

0条评论