mysql 里的 ibdata1 文件不断的增加

咱们在 Percona 支持栏目常常收到关于 MySQL 的 ibdata1 文件的这个问题。当监控服务器发送一个关于 MySQL 服务器存储的报警时,恐慌就开始了 —— 就是说磁盘快要满了。一番调查后你意识到大多数地盘空间被 InnoDB 的共享表空间 ibdata1 使用。而你已经启用了 innodb_file_per_table,因此问题是:php

ibdata1存了什么?

当你启用了 innodb_file_per_table,表被存储在他们本身的表空间里,可是共享表空间仍然在存储其它的 InnoDB 内部数据:html

  • 数据字典,也就是 InnoDB 表的元数据
  • 变动缓冲区
  • 双写缓冲区
  • 撤销日志

其中的一些在 Percona 服务器上能够被配置来避免增加过大的。例如你能够经过 innodb_ibuf_max_size 设置最大变动缓冲区,或设置 innodb_doublewrite_file 来将双写缓冲区存储到一个分离的文件。mysql

MySQL 5.6 版中你也能够建立外部的撤销表空间,因此它们能够放到本身的文件来替代存储到 ibdata1。能够看看这个文档ios

什么引发 ibdata1 增加迅速?

当 MySQL 出现问题一般咱们须要执行的第一个命令是:git

这将展现给咱们一些颇有价值的信息。咱们从** TRANSACTION(事务)**部分开始检查,而后咱们会发现这个github

这是一个最多见的缘由,一个14天前建立的至关老的事务。这个状态是活动的,这意味着 InnoDB 已经建立了一个数据的快照,因此须要在撤销日志中维护旧页面,以保障数据库的一致性视图,直到事务开始。若是你的数据库有大量的写入任务,那就意味着存储了大量的撤销页。sql

若是你找不到任何长时间运行的事务,你也能够监控INNODB STATUS 中的其余的变量,“History list length(历史记录列表长度)”展现了一些等待清除操做。这种状况下问题常常发生,由于清除线程(或者老版本的主线程)不能像这些记录进来的速度同样快地处理撤销。数据库

我怎么检查什么被存储到了 ibdata1 里了?

很不幸,MySQL 不提供查看什么被存储到 ibdata1 共享表空间的信息,可是有两个工具将会颇有帮助。第一个是马克·卡拉汉制做的一个修改版 innochecksum ,它发布在这个漏洞报告里。ruby

它至关易于使用:服务器

所有的 20608 中有 19272 个撤销日志页。这占用了表空间的 93%

第二个检查表空间内容的方式是杰里米·科尔制做的 InnoDB Ruby 工具。它是个检查 InnoDB 的内部结构的更先进的工具。例如咱们可使用 space-summary 参数来获得每一个页面及其数据类型的列表。咱们可使用标准的 Unix 工具来统计撤销日志页的数量:

尽管这种特殊的状况下,innochedcksum 更快更容易使用,可是我推荐你使用杰里米的工具去了解更多的 InnoDB 内部的数据分布及其内部结构。

好,如今咱们知道问题所在了。下一个问题:

我该怎么解决问题?

这个问题的答案很简单。若是你还能提交语句,就作吧。若是不能的话,你必需要杀掉线程开始回滚过程。那将中止 ibdata1 的增加,可是很显然,你的软件会出现漏洞,有些人会遇到错误。如今你知道如何去鉴定问题所在,你须要使用你本身的调试工具或普通的查询日志来找出谁或者什 么引发的问题。

若是问题发生在清除线程,解决方法一般是升级到新版本,新版中使用一个独立的清除线程替代主线程。更多信息查看该文档

有什么方法回收已使用的空间么?

没有,目前尚未一个容易而且快速的方法。InnoDB 表空间从不收缩...参见10 年之久的漏洞报告,最新更新自詹姆斯·戴(谢谢):

当你删除一些行,这个页被标为已删除稍后重用,可是这个空间从不会被回收。惟一的方法是使用新的 ibdata1 启动数据库。要作这个你应该须要使用 mysqldump 作一个逻辑全备份,而后中止 MySQL 并删除全部数据库、ib_logfile*、ibdata1* 文件。当你再启动 MySQL 的时候将会建立一个新的共享表空间。而后恢复逻辑备份。

总结

当 ibdata1 文件增加太快,一般是 MySQL 里长时间运行的被遗忘的事务引发的。尝试去解决问题越快越好(提交或者杀死事务),由于不通过痛苦缓慢的 mysqldump 过程,你就不能回收浪费的磁盘空间。

也是很是推荐监控数据库以免这些问题。咱们的 MySQL 监控插件包括一个 Nagios 脚本,若是发现了一个太老的运行事务它能够提醒你。

相关文章
相关标签/搜索