故障分析 | 从 data_free 异常说起

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 临时表 引发的data_free异常案例

一、前言
某个客户反馈查询数据库发现 information_schema.tables 的 data_free 值突发异常,达到 13G 左右。如图:

图片
需要排查什么原因导致的,本文梳理排查的过程和和解决问题的方法。

二、排查
2.1 分析
首先 data_free 的含义是 表空间 ibd 文件经过写入和删除之后,留下的没有回收的碎片空间大小。
让现场的同学同时检查主备库,对比有没有文件大小和配置上的差异。发现主库的data_free 值是 13G 左右, 备库正常。
image.png

看结果猜测和主库上的某些请求动作有关,空洞是 MySQL 因为 sql 写入而请求分配的空间没有自动回收的结果。基于前线给的信息,没有其他思路,再看前线发的截图:

image.png

意外从 截图的 ibtmp1 文件大小找到一些线索,截图显示 ibtmp1 文件大小也是 13G ,备库则是初始值大小。

image.png

忽略红色的箭头,查看 ibtmp1 文件大小为 13G ,似乎有些头绪,data_free 是否和 ibtmp1 有关。

2.2 验证猜想
使用 sysbench 创建测试表 sbtest1 ,构造2w条记录,然后创建 sbtest2 ,将 sbtest1 的数据 导入到 sbtest2 。为何这么操作,后面会说明。

mysql > show variables like 'innodb_temp_data_file_path';
Variable_name Value
innodb_temp_data_file_path ibtmp1:12M:autoextend

1 row in set (0.00 sec)

查看物理 ibtmp1 文件大小:

[root@tidb00 data]# du -sm ibtmp1
12 ibtmp1

构建测试用例,让系统自动生成临时表

mysql  > create table sbtest2 like sbtest1;
Query OK, 0 rows affected (0.01 sec)
mysql > insert into sbtest2(k,c,pad) select k,c ,pad from sbtest1;
Query OK, 200000 rows affected (1.18 sec)
Records: 200000  Duplicates: 0  Warnings: 0
mysql > insert into sbtest2(k,c,pad) select k,c ,pad from sbtest1;
Query OK, 200000 rows affected (1.06 sec)
mysql > insert into sbtest2(k,c,pad) select k,c ,pad from sbtest2;
Query OK, 400000 rows affected (2.49 sec)
Records: 400000  Duplicates: 0  Warnings: 0
mysql > insert into sbtest2(k,c,pad) select k,c ,pad from sbtest2;
Query OK, 800000 rows affected (6.18 sec)
Records: 800000  Duplicates: 0  Warnings: 0

再次检查 ibtmp1 文件大小 204MB

[root@tidb00 data]# du -sm ibtmp1
204 ibtmp1

mysql > SELECT FILE_NAME, TABLESPACE_NAME, ENGINE, INITIAL_SIZE, TOTAL_EXTENTS*EXTENT_SIZE
    ->        AS TotalSizeBytes, DATA_FREE, MAXIMUM_SIZE FROM INFORMATION_SCHEMA.FILES
    ->        WHERE TABLESPACE_NAME = 'innodb_temporary'\G
*************************** 1. row ***************************
      FILE_NAME: ./ibtmp1
TABLESPACE_NAME: innodb_temporary
         ENGINE: InnoDB
   INITIAL_SIZE: 12582912
 TotalSizeBytes: 213909504
      DATA_FREE: 207618048  ## 和物理文件大小对应
   MAXIMUM_SIZE: NULL
1 row in set (0.00 sec)

查看 I_S.tables 的data_free 的值:

image.png

查看 insert select from table 在执行过程中的确使用了临时表。

mysql > explain insert into sbtest2(k,c,pad) select k,c ,pad from sbtest2\G
*************************** 1. row ***************************
..
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: sbtest2
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1578168
     filtered: 100.00
        Extra: Using temporary  ## 
2 rows in set (0.00 sec)
Records: 200000  Duplicates: 0  Warnings: 0

至此,可以确定客户的实例因为执行某些 SQL 过程中占用系统临时表空间,使用完之后临时表空间并未被回收导致开头的问题。接下来我们详细了解 MySQL 临时表的相关知识。

三、临时表空间

3.1 介绍
ibtmp1 是非压缩的 innodb 临时表的独立表空间, 通过 innodb_temp_data_file_path参数指定文件的路径,文件名和大小,默认配置为ibtmp1:12M:autoextend,如果没有指定位置,临时表空间会被创建到innodb_data_home_dir 指定的路径。
需要注意的是: 按照默认值,这个文件大小是可以无限增长的。而且 5.7 版本并不会随着 SQL 语句结束主动回收该临时表空间,导致空间资源不足的安全风险。
3.2 什么情况下会用到临时表
当 explain 查看执行计划结果的 extra 列中,如果包含 Using Temporary 就表示会用到临时表,例如如下几种常见的情况通常就会用到:

insert into tab1 select ... from tab2 。

group by 无索引字段或 group by order by 的字段不一样。

distinct 的值和 group by 的值不一样,无法利用稀疏索引。

其他的欢迎补充。
3.3 临时表相关的参数和元数据
5.7 版本:

innodb_temp_data_file_path
default_tmp_storage_engine
internal_tmp_disk_storage_engine
8.0 版本分为会话级和全局级临时表空间

innodb_temp_tablespaces_dir #指定会话级创建临时表到BASEDIR/data/#innodb_temp
innodb_temp_data_file_path # 全局变量
internal_tmp_disk_storage_engine
用户自己创建的临时表可以通过查询 INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO

mysql > CREATE TEMPORARY TABLE t1 (c1 INT PRIMARY KEY) ENGINE=INNODB;
Query OK, 0 rows affected (0.00 sec)

mysql > SELECT * FROM INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO\G
1. row **

        TABLE_ID: 54
            NAME: #sqlfd5_b_0
          N_COLS: 4
           SPACE: 36

PER_TABLE_TABLESPACE: FALSE

   IS_COMPRESSED: FALSE

1 row in set (0.00 sec)
MySQL 在执行 sql 过程中被优化器创建的表,则无法通过 INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO 直接查看。比如本文的案例。

3.4 怎么解决 ibtmp1 文件空间占用的问题
万能的重启大法, 找个合适的时间,切换数据库,重启老的主库。
通过配置 innodb_temp_data_file_path 控制ibtmp1 文件的最大值,避免表空间大小无限增加。

innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:10G

12M是文件的初始大小,10G是文件的最大值,超过最大值则系统会提示报错

ERROR 1114 (HY000): The table '/data/msb_5_7_31/tmp#sql_xxxxx_0' is full

参考文章
https://dev.mysql.com/doc/refman/5.7/en/innodb-temporary-tablespace.html

https://dev.mysql.com/doc/refman/8.0/en/innodb-temporary-tablespace.html

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
存储 NoSQL Linux
MongoDB【部署 02】mongodb使用配置文件启动、添加为系统服务及自启动(一个报错:[13436][NotMasterOrSecondary])
MongoDB【部署 02】mongodb使用配置文件启动、添加为系统服务及自启动(一个报错:[13436][NotMasterOrSecondary])
1329 0
|
消息中间件 C语言 RocketMQ
消息队列 MQ操作报错合集之出现"Connection reset by peer"的错误,该如何处理
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
存储 缓存 监控
Vue.js 九个性能优化技巧
【10月更文挑战第16天】Vue.js 性能优化是一个持续的过程,需要我们不断地探索和实践。通过合理使用上述九个技巧,并结合具体的项目需求和性能指标,我们可以不断地提高 Vue.js 应用的性能和用户体验。
|
存储 NoSQL Shell
MongoDB 创建数据库
10月更文挑战第12天
769 4
|
存储 关系型数据库 MySQL
如何收缩Mysql的ibdata1文件
如何收缩Mysql的ibdata1文件
275 0
|
存储 缓存 监控
你的Redis真的变慢了吗?性能优化如何做
本文先讲述了Redis变慢的判别方法,后面讲述了如何提升性能。
103386 5
|
前端开发 JavaScript API
document.queryselector怎么用
document.queryselector怎么用
558 0
|
SQL 运维 数据管理
sql管理工具archery简介
Archery是一个多公司采用的SQL管理工具,提供权限管理、工作流配置、实例管理、SQL审核、查询、优化及通知功能。它支持多级审批和不同云环境的数据管理。尝试Archery的SaaS版本可访问[ArcheryDMS.com](https://archerydms.com/home/)。此外,NineData是一个综合平台,包含SQL开发、数据复制等功能,适应混合云和多云环境,由叶正盛创建,详情见[Ninedata.cloud](https://www.ninedata.cloud/aboutus)。
969 0
|
存储 缓存 监控
万能架构设计:ES+Redis+MySQL,这套组合可应对80%业务场景(2)
万能架构设计:ES+Redis+MySQL,这套组合可应对80%业务场景
32657 6
|
Java API 调度
xxl-job的原理(2)—调度中心管理注册信息
xxl-job的原理(2)—调度中心管理注册信息
1133 0
xxl-job的原理(2)—调度中心管理注册信息