如何:清理mysql InnoDB存储引擎?

时间:2010-10-13 20:22:48

标签: mysql innodb

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

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

3 个答案:

答案 0 :(得分:340)

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

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

InnoDB架构

InnoDB Architecture

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

我可以运行OPTIMIZE TABLE吗?

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

  • 使表格的数据和索引在ibdata1
  • 内连续
  • 使ibdata1增长,因为连续数据和索引页追加ibdata1

但是,您可以将表数据和表索引与ibdata1隔离开来,并单独管理它们。

我可以使用OPTIMIZE TABLE运行innodb_file_per_table吗?

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

好消息:当您启用OPTIMIZE TABLE时运行innodb_file_per_table,这将为该表生成.ibd个文件。例如,如果表mydb.mytable的数据库为/var/lib/mysql,则会生成以下内容:

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

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

错误消息:您所做的就是从生活在mydb.mytable中提取ibdata的数据页和索引页。每个表的数据字典条目(包括mydb.mytable)仍保留在数据字典中(请参阅Pictorial Representation of 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. 登录mysql并运行SET GLOBAL innodb_fast_shutdown = 0;(这将完全清除ib_logfile0ib_logfile1的所有剩余交易变更

  4. 关闭MySQL

  5. 将以下行添加到/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
    

    (旁注:无论您为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(这将重新创建ibdata1 [默认为10MB],ib_logfile0ib_logfile1每个1G)。

  8. 导入SQLData.sql

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

    例如,假设您有一个名为mydb.mytable的InnoDB表。如果您查看/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!

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

    CAVEAT

    在步骤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
    

    返回步骤6并继续

    更新2013-06-04 11:13 EDT

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

    回到July 03, 2006,Percona有一篇很好的文章why to choose a proper innodb_log_file_size。之后,在Nov 21, 2008,Percona跟进了另一篇关于how to calculate the proper size based on peak workload keeping one hour's worth of changes的文章。

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

    就个人而言,我仍会采用25%的规则进行初步设置。然后,由于工作负载可以在生产过程中随着时间的推移更准确地确定,you could resize the logs在维护周期内只需几分钟。

答案 1 :(得分:4)

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

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

答案 2 :(得分:1)

我按照本指南进行了完全重置(以 root 身份):

mysqldump --all-databases --single-transaction | gzip -c > /tmp/mysql.all.sql.gz
service mysql stop
mv /var/lib/mysql /var/lib/mysql.old; mkdir -m700 /var/lib/mysql; chown mysql:mysql /var/lib/mysql

mysql_install_db                # mysql 5.5
mysqld --initialize-insecure    # mysql 5.7

service mysql start
zcat /tmp/mysql.all.sql.gz | mysql
service mysql restart