Howto:清理一个mysql InnoDB存储引擎?

Bry*_*eld 128 mysql innodb

是否可以清理mysql innodb存储引擎,以便它不存储已删除表中的数据?

或者我每次都要重建一个新的数据库?

Rol*_*DBA 345

关于InnoDB,这是一个更完整的答案.这是一个漫长的过程,但值得努力.

请记住,这/var/lib/mysql/ibdata1是InnoDB基础架构中最繁忙的文件.它通常包含六种类型的信息:

InnoDB架构

InnoDB架构

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

我可以跑OPTIMIZE TABLE吗?

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

  • 使表的数据和索引在内部连续 ibdata1
  • 使得ibdata1成长,因为连续的数据和索引页被追加ibdata1

但是,您可以独立地隔离表数据和表索引ibdata1并对其进行管理.

我可以运行OPTIMIZE TABLE使用innodb_file_per_table

假设你要添加innodb_file_per_table/etc/my.cnf (my.ini).那么你可以OPTIMIZE TABLE在所有InnoDB表上运行吗?

好消息:当你启用运行OPTIMIZE TABLEinnodb_file_per_table,这将.ibd为该表生成一个文件.例如,如果你有表mydb.mytable难熬的datadir的/var/lib/mysql,它会产生如下:

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

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

坏消息:你所做的就是提取mydb.mytable生活中的数据页面和索引页面ibdata.每个表的数据字典条目(包括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
    
    Run Code Online (Sandbox Code Playgroud)
  3. 登录到MySQL和运行SET GLOBAL innodb_fast_shutdown = 0;(这将彻底冲洗所有剩下的事务变化ib_logfile0ib_logfile1)

  4. 关闭MySQL

  5. 将以下行添加到/etc/my.cnf(或my.ini在Windows上)

    [mysqld]
    innodb_file_per_table
    innodb_flush_method=O_DIRECT
    innodb_log_file_size=1G
    innodb_buffer_pool_size=4G
    
    Run Code Online (Sandbox Code Playgroud)

    (旁注:无论你的目标是什么,请innodb_buffer_pool_size确保innodb_log_file_size是25%innodb_buffer_pool_size.

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

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

  7. 启动MySQL(这将重新创建ibdata1[默认为10MB],ib_logfile0并且ib_logfile1每个都重建1G).

  8. 进口 SQLData.sql

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

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

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

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

我作为MySQL DBA在我的职业生涯中多次这样做过.事实上,我第一次这样做,我把50GB ibdata1文件缩减到只有500MB!

试试看.如果您对此有其他疑问,请询问.相信我; 这将在短期内和长期内发挥作用.

警告

在步骤6,如果由于mysql架构开始被删除而导致mysql无法重启,请回顾第2步.您制作了mysql架构的物理副本.您可以按如下方式恢复它:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql
Run Code Online (Sandbox Code Playgroud)

回到第6步并继续

更新2013-06-04 11:13美国东部时间

关于在步骤5 中将innodb_log_file_size设置为innodb_buffer_pool_size的 25%,这是一个相当古老的学校.

July 03, 2006回过头来,Percona有一篇很好的文章,为什么选择一个合适的innodb_log_file_size.之后,Nov 21, 2008Percona继续撰写另一篇文章,介绍如何根据峰值工作量计算合适的大小,保持一小时的变化.

我已经在DBA StackExchange中写了关于计算日志大小的帖子以及我在哪里引用了这两篇Percona文章.

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

  • 我还使用了innodb_file_per_table选项,效果很好,在一台服务器上有200个数据库,每个数据库有200个表,我能够将差异数据库符号链接到不同的分区,因此使用了更多的IO缓冲区和主轴,否则这些数据库可用:) (9认同)
  • 好上帝 我只是想说这可能是我见过的最好的答案之一,该死的好工作,先生.当我在导入154g db时获得ERROR 2013(HY000)时,帮助我找到了解决问题的方法.谢谢你的出色答案! (5认同)
  • 在32位系统中,不允许使用*innodb_buffer_pool_size*的4Gb值.Mysql将默认启动innodb禁用,恢复的表将更改为myisam.使用稍小的值来修复它. (3认同)
  • @SeanDowney BTW记得在必要时加注`innodb_open_tables`.默认值为300. (2认同)
  • @ giorgio79您需要将批量插入设置为更大的值.这是个好的观点.我将把问题的实质添加到我的答案中. (2认同)
  • MySQL性能博客指出“将日志大小设置为缓冲池大小的一部分的常见建议是错误的。” http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/ (2认同)

小智 5

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

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