一、问题现象
简单业务SQL也执行非常慢,processlist中监控语句特别慢,处于opening tables 状态
二、原因分析
1)实力负载并不大,几乎没有业务。
2)processlist中监控采集语句处于opening tables 状态;简单调大一倍table_open_cache,table_definition_cache后并没有效果。
3)偶尔的简单业务语句和简单管理查询语句也时快时慢(快的话0s慢的话10s+),也处于opening tables状态,被阻塞。
4)查询实例的业务表数量大概有40W个表。
MySQL5.7 中information_schema.tables表查询缓慢的原因?
查看执行计划中显示information_schema.tables是全表扫描且extra中显示Open_full_table
查询官方文档了解"优化information_schema查询”部分了解3个值含义:
官方为了让监控数据库而频繁使用information_schema下的表的查询更快,减少为了获取动态表的信息的文件操作,做了部分优化。
以下值表示适用于INFORMATION_SCHEMA表的查询的文件打开优化
- Skip_open_table:不需要打开表文件。通过扫描数据库目录,该信息已在查询中可用。
- Open_frm_only:只需要读取表信息(打开表的.frm文件)。
- Open_full_table:未优化的信息查找。必须读取表信息和表文件(打开.frm,.MYD和.MYI文件)。
MySQL5.7 使用文件系统作为数据字典,因此定位表需要文件系统操作,tables表中的一些数据甚至需要从文件中读取信息。这些都是缓慢的操作;Open_full_table and Scanned all databases意味着在所有库中找到的每个表,它都被打开(打开.frm,.MYD和.MYI文件)。所以当有许多表要扫描时,查询可能会花费很长时间,并对数据库的其余活动造成相对较大的影响,影响了业务语句的执行时间。
监控采集语句为表空间大小统计语句:
三、解决方案
临时措施:对于有大量业务表的实例,关闭information_schema表相关监控语句采集(参数table_open_cache,table_definition_cache也不能调成和业务表数量一样大,会占用大量的内存,有OOM风险)
长期措施:升级Mysql8.0(MySQL 8.0中引入了数据字典,数据存储在InnoDB表中,而不是磁盘上的frm文件,提高监控查询语句性能)
ps: MySQL 5.7监控语句采集information_schema.tables 也存在内存一直增长不释放的问题
1.升级mysql 到8.0版本,mysql 5.7 在2023年10月结束支持,且5.7上的该问题没有得到有效的解决;
2.监控时禁止采集information_schema 下的信息 ,但会影响监控信息的采集和使用;
3.短连接会出来类似问题更为严重,为避免这个问题可以将监控的短连接改成长连接。