Howto:清理mysql InnoDB存储引擎?

是否有可能清理mysql的innodb存储引擎,所以它不存储从删除的表中的数据?

或者我每次都必须重build一个新的数据库?

关于InnoDB,这是一个更完整的答案。 这是一个漫长的过程,但可以付出努力。

请记住, /var/lib/mysql/ibdata1是InnoDB基础架构中最繁忙的文件。 它通常有六种types的信息:

  • 表数据
  • 表索引
  • MVCC(Multiversioning并发控制)数据
    • 回滚段
    • 撤消空间
  • 表元数据(数据字典)
  • 双写缓冲区(防止依赖OScaching的背景写入)
  • 插入缓冲区(pipe理对非唯一二级索引的更改)
  • 参见Pictorial Representation of ibdata1Pictorial Representation of ibdata1

InnoDB架构

InnoDB架构

许多人创build了多个希望获得更好的磁盘空间pipe理和性能的ibdata文件,但是这种看法是错误的。

我可以运行OPTIMIZE TABLE吗?

不幸的是,对存储在共享表空间文件ibdata1中的InnoDB表运行OPTIMIZE TABLE ibdata1做两件事情:

  • 使表中的数据和索引在ibdata1ibdata1
  • 使ibdata1增长,因为连续的数据和索引页被附加ibdata1

但是,您可以从ibdata1分离表数据和表索引并独立pipe理它们。

我可以用innodb_file_per_table运行OPTIMIZE TABLE吗?

假设您将innodb_file_per_table添加到/etc/my.cnf (my.ini) 。 那么你能在所有的InnoDB表上运行OPTIMIZE TABLE吗?

好消息 :在启用innodb_file_per_table运行OPTIMIZE TABLE时,将为该表生成一个.ibd文件。 例如,如果你有mydb.mytable/var/lib/mysql datadir,它会产生以下结果:

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

.ibd将包含该表的数据页和索引页。 大。

坏消息 :您所做的mydb.mytableibdata提取mydb.mytable的数据页面和索引页面。 每个表(包括mydb.mytable的数据字典条目仍保留在数据字典中(请参见ibdata1的图示 )。 你不能只是简单地删除ibdata1这一点! 请注意, ibdata1并没有收缩。

InnoDB基础设施清理

要一劳永逸地收缩ibdata1 ,您必须执行以下操作:

  1. 将所有数据库转储(如mysqldump )到一个.sql文本文件(下面使用SQLData.sql

  2. 删除所有数据库( mysqlinformation_schema除外) CAVEAT :为了防范,请运行以下脚本以确保您拥有所有的用户权限:

     mkdir /var/lib/mysql_grants cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/. chown -R mysql:mysql /var/lib/mysql_grants 
  3. login到MySQL并运行SET GLOBAL innodb_fast_shutdown = 0; (这将完全清除ib_logfile0ib_logfile1所有剩余的事务性更改)

  4. closuresMySQL

  5. /etc/my.cnf添加到/etc/my.cnf (或Windows上的my.ini

     [mysqld] innodb_file_per_table innodb_flush_method=O_DIRECT innodb_log_file_size=1G innodb_buffer_pool_size=4G 

    (旁注:不pipe你为innodb_buffer_pool_size设置了innodb_buffer_pool_size ,确保innodb_log_file_sizeinnodb_buffer_pool_size 25%。

    另外: innodb_flush_method=O_DIRECT在Windows上不可用)

  6. 删除ibdata*ib_logfile* ,或者,可以删除/var/lib/mysql中除/var/lib/mysql/mysql之外的所有文件夹。

  7. 启动MySQL(这将重新创buildibdata1 [默认为10MB], ib_logfile0ib_logfile1 ,每个1G)。

  8. 导入SQLData.sql

现在, ibdata1仍然会增长,但只包含表元数据,因为每个InnoDB表将存在于ibdata1之外。 ibdata1将不再包含其他表的InnoDB数据和索引。

例如,假设您有一个名为mydb.mytable的InnoDB表。 如果您查看/var/lib/mysql/mydb ,您将看到两个表示该表的文件:

  • mytable.frm (存储引擎头)
  • mytable.ibd (表数据和索引)

使用/etc/my.cnfinnodb_file_per_table选项,可以运行OPTIMIZE TABLE mydb.mytable ,文件/var/lib/mysql/mydb/mytable.ibd将实际缩小。

在我的职业生涯中,我曾经多次做过MySQL DBA。 事实上,我第一次这样做,我把一个50GB的 ibdata1文件压缩到只有500MB!

试一试。 如果您对此有进一步的问题,请询问。 相信我; 这将在短期内以及长期的工作。

警告

在步骤6中,如果mysql由于mysql模式开始丢失而无法重新启动,请回头看一下步骤2.您已经创build了mysql模式的物理副本。 你可以恢复它如下:

 mkdir /var/lib/mysql/mysql cp /var/lib/mysql_grants/* /var/lib/mysql/mysql chown -R mysql:mysql /var/lib/mysql/mysql 

返回到第6步并继续

更新2013-06-04 11:13 EDT

关于在步骤5 中将 innodb_log_file_size设置为innodb_buffer_pool_size的 25%,这是一个比较老派的规则。

早在July 03, 2006July 03, 2006 ,Percona就有一篇不错的文章, 为什么要select合适的innodb_log_file_size 。 之后,在Nov 21, 2008Nov 21, 2008 ,Percona跟进了另一篇关于如何根据高峰工作量保持一小时的变化来计算适当规模的文章。

我已经在DBA StackExchange中写过关于计算日志大小的post,以及在哪里引用了这两个Percona文章。

  • Aug 27, 2012 : 在48GB内存的服务器上正确调整30GB InnoDB表
  • Jan 17, 2013 : MySQL 5.5 – Innodb – innodb_log_file_size高于4GB的总和?

就个人而言,我仍然会按照25%的规则进行初始设置。 然后,由于工作负载可以更准确地在生产中随时间确定,因此您可以在几分钟内在维护周期内调整日志的大小

InnoDB引擎不存储已删除的数据。 在插入和删除行时,在InnoDB存储文件中留下未使用的空间。 随着时间的推移,整体空间将不会减less,但随着时间的推移,数据库服务器会自动重新使用“已删除和已释放”的空间。

您可以通过手动重组表格来进一步调整和pipe理引擎使用的空间。 为此,请使用mysqldump转储受影响表中的数据,删除表,重新启动mysql服务,然后从转储文件重新创build表。

您可以定期使用OPTIMIZE TABLE查询来优化存储并加快SELECT查询的速度。 链接到MySQL手册: OPTIMIZE TABLE语法