0、导读

ibdata1文件是什么?

ibdata1是一个用来构建innodb系统表空间的文件,这个文件包含了innodb表的元数据、撤销记录、修改buffer和双写buffer。如果file-per-table选项打开的话,该文件则不一定包含所有表的数据。当innodb_file_per_table选项打开的话,新创建表的数据和索引则不会存在系统表空间中,而是存放在各自表的.ibd文件中.

显然这个文件会越来越大,innodb_autoextend_increment选项则指定了该文件每次自动增长的步进,默认是8M.

是什么原因导致ibdata1文件会越来越大?

ibdata1存放数据,索引和缓存等,是MYSQL的最主要的数据。所以随着数据库越来越大,表也会越大,这个无法避免的。如果时间长了,越来越大,我们在处理日志和空间的时候就不是那么方便了,就不知从何入手了。接下来我们就要处理下这样的情况,分库存储数据。

遇到InnoDB的共享表空间文件ibdata1文件大小暴增时,应该如何处理?

1、问题背景

用MySQL/InnoDB的童鞋可能也会有过烦恼,不知道为什么原因,ibdata1文件莫名其妙的增大,不知道该如何让它缩回去,就跟30岁之后男人的肚腩一样,汗啊,可喜可贺的是我的肚腩还没长出来,hoho~

正式开始之前,我们要先知道ibdata1文件是干什么用的。

ibdata1文件是InnoDB存储引擎的共享表空间文件,该文件中主要存储着下面这些数据:

data dictionary

double write buffer

insert buffer/change buffer

rollback segments

undo space

Foreign key constraint system tables

另外,当选项 innodb_file_per_table = 0 时,在ibdata1文件中还需要存储 InnoDB 表数据&索引。ibdata1文件从5.6.7版本开始,默认大小是12MB,而在这之前默认大小是10MB,其相关选项是 innodb_data_file_path,比如我一般是这么设置的:

innodb_data_file_path = ibdata1:1G:autoextend

当然了,无论是否启用了innodb_file_per_table = 1,ibdata1文件都必须存在,因为它必须存储上述 InnoDB 引擎所依赖&必须的数据,尤其是上面加粗标识的 rollback segments 和 undo space,它俩是引起 ibdata1 文件大小增加的最大原因,我们下面会详细说。

2、原因分析

我们知道,InnoDB是支持MVCC的,它和ORACLE类似,采用 undo log、redo log来实现MVCC特性的。在事务中对一行数据进行修改时,InnoDB 会把这行数据的旧版本数据存储一份在undo log中,如果这时候有另一个事务又要修改这行数据,就又会把该事物最新可见的数据版本存储一份在undo log中,以此类推,如果该数据当前有N个事务要对其进行修改,就需要存储N份历史版本(和ORACLE略有不同的是,InnoDB的undo log不完全是物理block,主要是逻辑日志,这个可以查看 InnoDB 源码或其他相关资料)。这些 undo log 需要等待该事务结束后,并再次根据事务隔离级别所决定的对其他事务而言的可见性进行判断,确认是否可以将这些 undo log 删除掉,这个工作称为 purge(purge 工作不仅仅是删除过期不用的 undo log,还有其他,以后有机会再说)。

那么问题来了,如果当前有个事务中需要读取到大量数据的历史版本,而该事务因为某些原因无法今早提交或回滚,而该事务发起之后又有大量事务需要对这些数据进行修改,这些新事务产生的 undo log 就一直无法被删除掉,形成了堆积,这就是导致 ibdata1 文件大小增大最主要的原因之一。这种情况最经典的场景就是大量数据备份,因此我们建议把备份工作放在专用的 slave server 上,不要放在 master server 上。

另一种情况是,InnoDB的 purge 工作因为本次 file i/o 性能是在太差或其他的原因,一直无法及时把可以删除的 undo log 进行purge 从而形成堆积,这是导致 ibdata1 文件大小增大另一个最主要的原因。这种场景发生在服务器硬件配置比较弱,没有及时跟上业务发展而升级的情况。

比较少见的一种是在早期运行在32位系统的MySQL版本中存在bug,当发现待 purge 的 undo log 总量超过某个值时,purge 线程直接放弃抵抗,再也不进行 purge 了,这个问题在我们早期使用32位MySQL 5.0版本时遇到的比较多,我们曾经遇到这个文件涨到100多G的情况。后来我们费了很大功夫把这些实例都迁移到64位系统下,终于解决了这个问题。

最后一个是,选项 innodb_data_file_path 值一开始就没调整或者设置很小,这就必不可免导致 ibdata1 文件增大了。Percona官方提供的 my.cnf 参考文件中也一直没把这个值加大,让我百思不得其解,难道是为了像那个经常被我吐槽的xx那样,故意留个暗门,好方便后续帮客户进行优化吗?(我心理太阴暗了,不好不好~~)

稍微总结下,导致ibdata1文件大小暴涨的原因有下面几个:

有大量并发事务,产生大量的undo log;

有旧事务长时间未提交,产生大量旧undo log;

file i/o性能差,purge进度慢;

初始化设置太小不够用;

32-bit系统下有bug。

稍微题外话补充下,另一个热门数据库 PostgreSQL 的做法是把各个历史版本的数据 和 原数据表空间 存储在一起,所以不存在本案例的问题,也因此 PostgreSQL 的事务回滚会非常快,并且还需要定期做 vaccum 工作(具体可参见PostgreSQL的MVCC实现机制,我可能说的不是完全正确哈)

3、解决方法建议

看到上面的这些问题原因描述,有些同学可能觉得这个好办啊,对 ibdata1 文件大小进行收缩,回收表空间不就结了吗。悲剧的是,截止目前,InnoDB 还没有办法对 ibdata1 文件表空间进行回收/收缩,一旦 ibdata1 文件的肚子被搞大了,只能把数据先备份后恢复再次重新初始化实例才能恢复原先的大小,或者把依次把各个独立表空间文件备份恢复到一个新实例中,除此外,没什么更好的办法了。

当然了,这个问题也并不是不能防范,根据上面提到的原因,相应的建议对策是:

升级到5.6及以上(64-bit),采用独立undo表空间,5.6版本开始就支持独立的undo表空间了,再也不用担心会把 ibdata1 文件搞大;

初始化设置时,把 ibdata1 文件至少设置为1GB以上;

增加purge线程数,比如设置 innodb_purge_threads = 8;

提高file i/o能力,该上SSD的赶紧上;

事务及时提交,不要积压;

默认打开autocommit = 1,避免忘了某个事务长时间未提交;

检查开发框架,确认是否设置了 autocommit=0,记得在事务结束后都有显式提交或回滚。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

您可能感兴趣的文章:mysql 误删除ibdata1之后的恢复方法

MySQL的InnoDB扩容及ibdata1文件瘦身方案完全解析

完美解决mysql启动后随即关闭的问题(ibdata1文件损坏导致)

mysql初始化ibdata1大小_MySQL问答系列之如何避免ibdata1文件大小暴涨相关推荐

  1. mysql初始化root密码_MySQL初始化root密码的正确操作流程

    此文章主要向大家描述的是MySQL初始化root密码与允许远程访问的正确操作步骤与实际应用代码的描述,假如你对允许MySQL远程访问的实际操作有兴趣了解的话,以下的文章将满足你对其的好奇之心. MyS ...

  2. mysql 创建临时表 时间类型_MySQL问答系列之什么情况下会用到临时表

    临时表介绍 什么是临时表:MySQL用于存储一些中间结果集的表,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间.为什么会产生临时表:一般是由于复杂的SQL导致临时表被大量创 ...

  3. mysql 默认page大小_MySQL innodb_page_size

    原标题:MySQL innodb_page_size 墨墨导读:Page是MySQL Innodb存储的最基本结构,也是Innodb磁盘管理的最小单位,了解page的一些特性,可以更容易理解MySQL ...

  4. mysql数据库内存分配_MySQL OOM 系列一 Linux内存分配

    RDS(网易云关系数据库服务)上线已经有一段时间,陆续不断有产品迁入到了RDS中,在线上运维的过程中,也遇到了一些曾经没有考虑到,或者考虑的不全的东西.后续有时间可以分享给大家. 今天想提到的是线上一 ...

  5. mysql 二进制日志大小_mysql二进制日志。

    mysql二进制日志: 命令行参数: --log-bin[=file_name]   文件名 --log-bin-index[=file]文件索引 --max_binlog_size     单个文件 ...

  6. mysql 数据库 限制大小_MySQL数据库表各种大小限制小结

    本文所有条目总结均来自mysql5.6的官网英文文档: 1. MySQL表的列数限制 1.1 MySQL硬性限制每个表最大4096个列 1.2 InnoDB存储引擎的约束: 每个表最大1017个列; ...

  7. mysql查看导入大小_mysql 数据导入、导出,及库大小查看

    一.导出数据库用mysqldump命令(注意mysql的安装路径,即此命令的路径): 1.导出数据和表结构: mysqldump -u用户名 -p密码 数据库名 > 数据库名.sql #/usr ...

  8. mysql ip比较大小_MySQL优化/面试,看这一篇就够了

    原文链接:http://www.zhenganwen.top/articles/2018/12/25/1565048860202.html 作者:Anwen~ 链接:https://www.nowco ...

  9. mysql 二进制日志大小_mysql二进制日志相关参数

    1,binlog_cache_size和max_binlog_cache_size 表示的为每个session的事物分配的缓存 当插入或者修改数据的时候,不会立刻写入磁盘,而是会缓存起来,缓存的大小由 ...

最新文章

  1. 智能算法中终止条件: “最大评估次数” or “最大迭代次数”
  2. FastAPI 之自动化测试数据库接口
  3. webbrowser selstart selLength
  4. GPS Essentials
  5. SSL 1760——商店选址问题(最短路)
  6. Angular input控件的click事件表达式如何被转换成JavaScript函数
  7. 【ES6(2015)】RegExp
  8. 数据库存入表情符报错问题
  9. 聊聊Spring家族中的那几百个注解
  10. zabbix自定义监控nginx
  11. urule决策引擎实现增量打包部署
  12. Oracle导出数据中的prompt,set feedback 等是什么意思
  13. 2018年上半年阅读总结(系统架构师)
  14. 大规模网络拓扑测量与分析研究1-论文
  15. php7语法 mysql_php7语法
  16. 保姆级教程:手把手教你搭建个人网站
  17. 关于docker容器启动后修改或添加端口
  18. modelsim的基本使用
  19. Open Inventor 在STK 模型转换中的应用
  20. 微信小程序成长记录(一)

热门文章

  1. 【SQLite预习课2】SQLite 和 HeidiSQL 的安装
  2. 利用python制作转盘
  3. 如何把Mrakdown格式的博客文章原封不动的打印下来?
  4. 用Matlab绘制相平面图
  5. 花瓶(Charles)的域名映射(map remote)功能不管用
  6. SQL面试题:经典排名问题(相同分数是否要并列,排名是否有间隔)
  7. 沈阳市计算机学校辛亮,2017-2018学年度(下)听评课总结.doc
  8. php对联广告,纯DIV/CSS对联漂浮广告代码(无JS)
  9. linux 磁盘不回收站,避免误删文件:Linux回收站机制
  10. APP报毒的自查方法