赞
踩
ibdata1是一个用来构建innodb系统表空间的文件
上面是一个数据库ibdata1文件,达到了780多G,而且还在不断增长。
这个文件包含了innodb数据字典、修改buffer和双写buffer、撤销日志,还包含在用户在系统表空间创建的表信息和索引数据
显然,由于所有表的数据索引和缓存都存在这个文件中,随着数据库的不断增大,这个文件肯定会越来越大的。
和系统表空间(也称作共享表空间)对应,MySQL提供了另外一种存储文件的方式:独立表空间。
独立表空间模式下,每个innodb表都有自己独立的表空间文件(.ibd文件),存储各种表的索引和数据。
通过配置项:innodb_file_per_table指定MySQL使用独立表空间,MySQL5.6.6以后的版本默认值是ON。MySQL5.6.5以前的版本默认值是OFF。
如果当前MySQL使用系统表空间的模式,是无法在开启数据库的情况下进行切换到共享表空间的。必须关闭MySQL重建数据结构。步骤如下:
使用mysqldump备份所有InnoDB数据表,包括MySQL的系统表。
使用下面的命令可以参考当前系统表:
SELECT TABLE_NAME from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='mysql' and ENGINE='InnoDB';
MySQL5.6中包含五张系统表:
如果数据库只用了InnoDB表,可以直接备份所有数据库。
mysqldump -h localhost -uroot -pxxxxx –all-databases > dump.sql
使用mysqld_safe关闭MySQL服务。
mysqladmin -uroot -pxxxxx shutdown
首先需要删除当前存在的所有表空间文件(.idb),包括ibdata1和ib_log文件,以及数据库自带的.idb文件。
然后需要删除所有的表结构描述文件:*.frm。位于数据库名称相应的文件夹下。
在数据库配置文件my.cnf中的[mysqld]下添加innodb_file_per_table=1配置。
[mysqld]
innodb_file_per_table=1
最后使用新的配置文件重新启动mysql服务。
mysqld_safe --defaults-file=/your/config/path/my.cnf &
然后导入mysaldump备份的数据
# 登录进入mysql
mysql -hlocalhost -uroot -pxxxxx database_name
# 导入数据
source /your/backup/file/path/dump.sql
刚开始建立数据库时,就推荐使用独立表空间,MySQL5.6.6以后的版本默认是独立表空间。
使用独立表空间很显然能够提高存储效率,拆分表和表之间的耦合,将对数据库的操作粒度降低到表级别。
独立表空间对于存储优化,迁移,备份,恢复和监控来说,都更加灵活和强大。下面列举一些代表性的好处:
关于 MySQL 的 ibdata1 文件的这个问题:
当监控服务器发送一个关于 MySQL 服务器存储的报警时,恐慌就开始了 —— 就是说磁盘快要满了。
一番调查后你意识到大多数地盘空间被 InnoDB 的共享表空间 ibdata1 使用。而你已经启用了innodb_file_per_table
当你启用了 innodb_file_per_table,表被存储在他们自己的表空间里,但是共享表空间仍然在存储其它的 InnoDB 内部数据:
其中的一些在 Percona 服务器上可以被配置来避免增长过大的。例如你可以通过 innodb_ibuf_max_size 设置最大变更缓冲区,或设置 innodb_doublewrite_file 来将双写缓冲区存储到一个分离的文件。
MySQL 5.6 版中你也可以创建外部的撤销表空间,所以它们可以放到自己的文件来替代存储到 ibdata1。可以看看这个文档。
当 MySQL 出现问题通常我们需要执行的第一个命令是:
SHOW ENGINE INNODB STATUS/G
这将展示给我们一些很有价值的信息。我们从** TRANSACTION(事务)**部分开始检查,然后我们会发现这个:
:::tips
很不幸,MySQL 不提供查看什么被存储到 ibdata1 共享表空间的信息,但是有两个工具将会很有帮助。第一个是马克·卡拉汉制作的一个修改版 innochecksum ,它发布在这个漏洞报告里。
它相当易于使用:
:::tips
0 bad checksum
13 FIL_PAGE_INDEX
19272 FIL_PAGE_UNDO_LOG
230 FIL_PAGE_INODE
1 FIL_PAGE_IBUF_FREE_LIST
892 FIL_PAGE_TYPE_ALLOCATED
2 FIL_PAGE_IBUF_BITMAP
195 FIL_PAGE_TYPE_SYS
1 FIL_PAGE_TYPE_TRX_SYS
1 FIL_PAGE_TYPE_FSP_HDR
1 FIL_PAGE_TYPE_XDES
0 FIL_PAGE_TYPE_BLOB
0 FIL_PAGE_TYPE_ZBLOB
0 other
3 max index_id
全部的 20608 中有 19272 个撤销日志页。这占用了表空间的 93%。
:::
第二个检查表空间内容的方式是杰里米·科尔制作的 InnoDB Ruby 工具。它是个检查 InnoDB 的内部结构的更先进的工具。例如我们可以使用 space-summary 参数来得到每个页面及其数据类型的列表。我们可以使用标准的 Unix 工具来统计撤销日志页的数量:
:::tips
19272
:::
尽管这种特殊的情况下,innochedcksum 更快更容易使用,但是我推荐你使用杰里米的工具去了解更多的 InnoDB 内部的数据分布及其内部结构。
这个问题的答案很简单。如果你还能提交语句,就做吧。如果不能的话,你必须要杀掉线程开始回滚过程。那将停止 ibdata1 的增长,但是很显然,你的软件会出现漏洞,有些人会遇到错误。现在你知道如何去鉴定问题所在,你需要使用你自己的调试工具或普通的查询日志来找出谁或者什么引起的问题。
如果问题发生在清除线程,解决方法通常是升级到新版本,新版中使用一个独立的清除线程替代主线程。更多信息查看该文档
没有,目前还没有一个容易并且快速的方法。InnoDB 表空间从不收缩…参见10 年之久的漏洞报告,最新更新自詹姆斯·戴(谢谢):
当你删除一些行,这个页被标为已删除稍后重用,但是这个空间从不会被回收。唯一的方法是使用新的 ibdata1 启动数据库。要做这个你应该需要使用 mysqldump 做一个逻辑全备份,然后停止 MySQL 并删除所有数据库、ib_logfile*、ibdata1* 文件。当你再启动 MySQL 的时候将会创建一个新的共享表空间。然后恢复逻辑备份。
当 ibdata1 文件增长太快,通常是 MySQL 里长时间运行的被遗忘的事务引起的。尝试去解决问题越快越好(提交或者杀死事务),因为不经过痛苦缓慢的 mysqldump 过程,你就不能回收浪费的磁盘空间。
也是非常推荐监控数据库以避免这些问题。我们的 MySQL 监控插件包括一个 Nagios 脚本,如果发现了一个太老的运行事务它可以提醒你。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。