【MySQL】ibdata文件增大的原因

背景
  早上和一个同事讨论技术问题,谈到ibdata文件会随着数据的使用而增大,而且在事务隔离级别RR 隔离级别下要比RC 隔离级别的大。本文尝试分析两个问题之一
 a ibdata 文件随着数据库的使用而增大。
 b RR 隔离级别下比RC 隔离级别下增长的快大。
ibdata1 存放哪些数据?
表数据/索引 (innodb_file_per_table=0 时)
data dictionary aka metadata of InnoDB tables
undo 表空间 回滚段相关记录
doublewrite buffer
change buffer
什么原因导致ibdata 迅速增大呢?
从ibdata1文件存放的内容来分析
我们都知道innodb的表有两种存放方式:
当innodb_file_per_table=0时也即共享表空间方式,所有表的索引/数据统一存放在一个共享表空间中ibdata1文件,随着数据量的增大,共享表空间的文件大小也迅速增长,同时空间回收困难;
当innodb_file_per_table=1时也即独占表空间方式,也就是一张表一个表空间(ibd文件),表中的索引和数据存放在独立的表空间中,执行drop/truncate 操作可以快速的回收独立表空间。
对于buffer 可以分别使用参数 innodb_doublewrite_file ,innodb_ibuf_max_size控制大小,他们带来的空间增长可以忽略不计, 最终  ibdata最终的大小取决于事务的大小/长短。
a 数据库系统中存在长时间未提交的事务,或者在同一个事务中更新/插入很多数据,导致innodb需要维护很大的undo segments来保障一致性读。
通过执行命令
SHOW ENGINE INNODB STATUSG
---TRANSACTION 36E, ACTIVE 1256288 sec
MySQL thread id 42, OS thread handle 0x7f8baaccc700, query id 7900290 localhost root
show engine innodb status
Trx read view will not see trx with id >= 36F, sees < 36F
例子中显示有一个长达 1256288秒(14年)的事务未提交。active 意味着innodb在undo segment里面创建数据的快照以便提供一致性读。如果数据库存在大量的长事务,就要耗费大量的undo segment。
b 5.5版本之前 purge undo thread是和master thread 共用的。存在大量长事务的时候导致purge undo的速度小于undo segment产生的速度。通过 innodb 参数 History list length

  1. ------------
  2. TRANSACTIONS
    ------------
    Trx id counter 43831607347
    Purge done for trx's n:o < 43831607342 undo n:o < 0 state: running but idle
    History list length 2308
    LIST OF TRANSACTIONS FOR EACH SESSION:
History list length  2308 表示有 2308个事务没有清理,过大的值意味着purge thread 速度达到了瓶颈。5.5 版本开始MySQL 将purge thread 和master thread 分开,我们可以通过调整参数来加快purge undo的速度。
# yzsql 3311 param purge
  1. Variable_name                Value
  2. innodb_max_purge_lag          0
  3. innodb_max_purge_lag_delay    0
  4. innodb_purge_batch_size       300
  5. innodb_purge_threads          12
如何查看ibdata文件中的内容呢?
MySQL 官方并没有提供工具查ibata存储了什么内容,不过我们可以通过如下两种工具
innochecksum,(感谢  Mark Callaghan)。
 ./innochecksum /var/lib/mysql/ibdata1

  1. 0     bad checksum
  2. 13    FIL_PAGE_INDEX
  3. 19272 FIL_PAGE_UNDO_LOG --占用了总ibdata1 的93%
  4. 230   FIL_PAGE_INODE
  5. 1     FIL_PAGE_IBUF_FREE_LIST
  6. 892   FIL_PAGE_TYPE_ALLOCATED
  7. 2     FIL_PAGE_IBUF_BITMAP
  8. 195   FIL_PAGE_TYPE_SYS
  9. 1     FIL_PAGE_TYPE_TRX_SYS
  10. 1     FIL_PAGE_TYPE_FSP_HDR
  11. 1     FIL_PAGE_TYPE_XDES
  12. 0     FIL_PAGE_TYPE_BLOB
  13. 0     FIL_PAGE_TYPE_ZBLOB
  14. 0     other
  15. 3     max index_id
从上面的分析来看 undo log占用了总ibdata1 的93%。
第二个工具: innodb_space (  made by Jeremy Col)可以清晰地分析出ibdata1的组成(该工具需要bindata环境)
  1. # innodb_space -f /var/lib/mysql/ibdata1 space-summary | grep UNDO_LOG | wc -l
  2. 19272
如何解决 ibdata1 不停的增大呢? 
坦白的说我们没有方法阻止其不停的增大,但是我们可以使用
1 规范开发同学的数据库使用习惯,使用短小的事务替代大事务,并确保每个事务都有commit机制。
2 增加purge thread 数量,加快purge undo的速度尽快释放undo空间。
3 升级到5.6 版本 独立出undo 表空间来保持ibdata文件在一个合理的大小。
当然我们也没有优雅的办法上增大的ibdata文件缩小,这个文件只增加不减小。

参考资料
[1]  Reasons for run-away main Innodb Tablespace 
[2]  Why is the ibdata1 file continuously growing in MySQL? 
[3]  http://bugs.mysql.com/bug.php?id=1341




来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22664653/viewspace-1994016/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/22664653/viewspace-1994016/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 中,ibdata1 是 InnoDB 存储引擎的系统表空间,它存储了表、索引和事务等的元数据信息。因为 ibdata1 文件的大小是动态增长的,所以如果不进行定期清理,它可能会占据大量的磁盘空间。下面是一些清理 ibdata1 的方法: 1. 清理未使用的 InnoDB 表 使用以下命令可以查找未使用的 InnoDB 表: ``` SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema') AND ENGINE = 'InnoDB' AND TABLE_NAME NOT IN ( SELECT DISTINCT TABLE_NAME FROM information_schema.statistics WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema') ); ``` 如果查询结果为空,则表示所有 InnoDB 表都在使用中,否则需要进一步分析并删除未使用的表。 2. 清理 InnoDB 日志文件MySQL 中,InnoDB 存储引擎会生成两个日志文件ib_logfile0 和 ib_logfile1。这些日志文件记录了 InnoDB 存储引擎的所有操作,包括事务的提交和回滚。如果这些日志文件过大,可以通过以下命令清理: ``` SET GLOBAL innodb_fast_shutdown = 0; ``` 然后重启 MySQL 服务器,这样会清理掉不必要的日志文件。 3. 重建 InnoDB 表 如果 InnoDB 表中存在大量已删除的数据,可以通过以下方法进行重建: ``` ALTER TABLE table_name ENGINE=InnoDB; ``` 这样可以重建表并清理掉已删除的数据。 4. 导出并重新导入数据库 如果以上方法无法清理 ibdata1 文件,可以考虑将数据库导出为 SQL 文件,删除原数据库并重新创建一个空的数据库,然后再将 SQL 文件重新导入。这样可以清理掉所有不必要的数据和元数据信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值