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

还是每次都要重建一个新的数据库?

推荐答案

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

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

InnoDB Architecture

InnoDB架构

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

Can I run OPTIMIZE TABLE ?

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

  • 使表的数据和索引在ibdata1以内连续
  • 使ibdata1增长,因为连续数据页和索引页是appendedibdata1

但是,您可以将表数据和表索引从ibdata1中分离出来,并独立管理它们.

Can I run OPTIMIZE TABLE with innodb_file_per_table ?

假设你把innodb_file_per_table/etc/my.cnf (my.ini)相加.你能在所有InnoDB表上运行OPTIMIZE TABLE吗?

Good News:当您在启用innodb_file_per_table的情况下运行OPTIMIZE TABLE时,这将为该表生成一个.ibd文件.例如,如果表mydb.mytable的datadir为/var/lib/mysql,它将产生以下结果:

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

.ibd将包含该表的数据页和索引页.太棒了

Bad News:你所做的就是从living in ibdata中提取mydb.mytable的数据页和索引页.每个表(包括mydb.mytable)的数据字典条目仍保留在数据字典中(参见Pictorial Representation of ibdata1).YOU CANNOT JUST SIMPLY DELETE 104 AT THIS POINT !!!请注意ibdata1根本没有缩水.

InnoDB Infrastructure Cleanup

要一次性收缩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

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

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

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

使用/etc/my.cnf中的innodb_file_per_table选项,可以运行OPTIMIZE TABLE mydb.mytable,而文件/var/lib/mysql/mydb/mytable.ibd实际上会收缩.

在MySQL DBA的职业生涯中,我已经做过很多次了.事实上,我第一次这样做时,我将50GBibdata1文件缩小到只有500MB!

试试看.如果你对此有进一步的问题,尽管问.相信我;这将在短期和长期内奏效.

CAVEAT

在第6步,如果mysql因为mysql模式begin被删除而无法重新启动,请回顾第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并继续

UPDATE 2013-06-04 11:13 EDT

关于在第5步中设置innodb_log_file_size%到25%的innodb_buffer_pool_size,这是一条很老套的规则.

回到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上写过关于计算日志(log)大小的帖子,以及我在哪里引用了这两篇Percona文章.

就我个人而言,对于初始设置,我仍然会遵循25%的规则.然后,随着生产时间的推移,工作量可以更准确地确定,在一个维护周期内,只需几分钟就可以确定you could resize the logs.

Mysql相关问答推荐

SQL计算不同的列并返回所有行

SQL/Pyspark -判断条件

如何在sql中包含0作为计数?

Mysql:使用like Select 查询

MySQL 运行自动脚本

避免多个SQL查询的重构代码

检索按键列值分组的最新日期 (MySql)

为什么一个 10 位的电话号码不能存储在长度为 10 的整数中?

MySQL过滤食谱上的多对多 - 成分表

Mysql insert with loop out of select 语句

如果在表中多次发现 a 列中的相同值,则排除所有行

如果我创建一个没有主键的表然后添加一个主键,主键是聚集索引吗?

DECIMAL(m, n) 在 64 位系统中如何表示?

加快 MySQL 中的行计数

从一个带有连接的表中删除

Drupal 的默认密码加密方法是什么?

在 MYSQL 中按枚举字段排序

MySQL - 错误 1045 - 访问被拒绝

在 MySQL 中的子查询上使用 GROUP_CONCAT

cron 启动的 mysqldump 和密码安全