排查主备节点存储空间不一致问题

数据库关系型数据库技术服务知识库
问题现象

用户使用火山引擎 RDS for MySQL 高可用版实例,整个集群具有一个主节点,一个备节点,三个只读节点,发现其中一个只读节点磁盘占用率高,我们该如何排查此类问题?

排查步骤

查看碎片率

查看每个数据库占用的空间大小以及碎片大小:

SELECT
 SUBSTRING_INDEX( it.NAME, '/', 1 ) AS table_schema,
 ROUND( SUM( its.allocated_size ) / 1024 / 1024 / 1024, 2 ) "size in GB",
 ROUND( SUM( t.data_free ) / 1024 / 1024 / 1024, 2 ) "fragmented size in GB" 
FROM
 information_schema.innodb_tables it
 INNER JOIN information_schema.innodb_tablespaces its ON it.space = its.space
 INNER JOIN information_schema.innodb_tablestats istat ON istat.table_id = it.table_id
 INNER JOIN information_schema.TABLES t ON t.table_schema = SUBSTRING_INDEX( it.NAME, '/', 1 ) 
 AND t.table_name = SUBSTRING_INDEX( it.NAME, '/', - 1 ) 
GROUP BY 1 
ORDER BY 2 DESC;

查看临时文件

临时文件的使用主要有如下场景:

  1. 在 DDL 过程中创建的临时文件。
  2. 优化器创建的临时文件,复杂的 SQL 语句在引擎层需要依赖隐式临时表来辅助计算,在 Server 层可能也会创建临时文件来存储临时结果,比如 order by 操作。
  3. binlog 产生的临时文件。

运行如下语句查看临时表空间占用情况:

mysql> SELECT file_name, tablespace_name, table_name, engine, index_length, total_extents, extent_size from information_schema.files WHERE file_name LIKE '%ibt%';

查看文件大小

在 MySQL 5.7 及更高版本或 MySQL 8.0 及更高版本中获得文件大小

mysql> SELECT file_name, tablespace_name, table_name, engine, index_length, total_extents, extent_size from information_schema.files ;

主库输出结果如下: 图片 从库输出结果: 图片 从结果上来看,此只读节点上,undo 表空间文件空间占用异常,总大小为 TOTAL_EXTENTS x EXTENT_SIZE,约为 25GB。需要排查 undo 表空间异常的问题。

根因描述

Undo Log 是 InnoDB 十分重要的组成部分,主要作用为:

  • 并发控制(Concurrency Control)
  • 故障恢复(Crash Recovery)

我们怀疑在此只读节点上存在长时间未提交的 SQL,阻塞了 undo 的 purge 操作。 查看 show engine innodb status:

------------
TRANSACTIONS
------------
Trx id counter 1139855969
Purge done for trx's n:o < 1077956438 undo n:o < 3 state: running but idle
History list length 29096470

使用 show full processlist 查看当前的连接信息:

mysql> show full processlist;
+----------+--------------------+----------------------+--------------------+------------------+----------+---------------+-----------------------+
| Id       | User               | Host                 | db                 | Command          | Time     | State         | Info                  |
+----------+--------------------+----------------------+--------------------+------------------+----------+---------------------------------------+
| 36891633 | appa_rds_admin     | 172.xx.xxx.xxx:xxxxx | apply              | Execute          |   765967 | executing     | select count(*)...... |

因为 MySQL InnoDB 使用了 Undo Log 中记录的历史版本数据来满足 MVCC 的需求,存在长时间未执行完的 SQL / 未提交的事务,会阻塞 undo 的清理动作。

解决方案

在此场景中,只需要 kill 掉次长时间运行的 SQL,即可使 MySQL 回收 undo 表空间。在后续的使用中,我们建议:

  1. 老生常谈的,避免大事务,长事务,事务要及时进行提交,优化 SQL 语句。
  2. 可以在参数组中设置 max_execution_time,超出此执行后自动 kill SQL。此参数设定需要依据业务场景来定。
参考文档
0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论