是否可以清理mysql innodb存储引擎,以便它不存储已删除表中的数据?
或者我每次都必须重建一个新的数据库吗?
答案 0 :(得分:340)
关于InnoDB,这是一个更完整的答案。这是一个漫长的过程,但值得付出努力。
请记住,/var/lib/mysql/ibdata1
是InnoDB基础架构中最繁忙的文件。它通常包含六种类型的信息:
Pictorial Representation of ibdata1
许多人创建多个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
根本没有缩小。
要一次性缩小ibdata1
,您必须执行以下操作:
转储(例如,使用mysqldump
)所有数据库到.sql
文本文件(SQLData.sql
下方使用)
删除所有数据库(mysql
和information_schema
除外) CAVEAT :作为预防措施,请运行此脚本以确保您拥有所有用户资助到位:
mkdir /var/lib/mysql_grants
cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
chown -R mysql:mysql /var/lib/mysql_grants
登录mysql并运行SET GLOBAL innodb_fast_shutdown = 0;
(这将完全清除ib_logfile0
和ib_logfile1
的所有剩余交易变更
关闭MySQL
将以下行添加到/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_size
为innodb_buffer_pool_size
的25%。
另外:innodb_flush_method=O_DIRECT
在Windows上不可用)
删除ibdata*
和ib_logfile*
,您可以选择删除/var/lib/mysql
中的所有文件夹,/var/lib/mysql/mysql
除外。
启动MySQL(这将重新创建ibdata1
[默认为10MB],ib_logfile0
和ib_logfile1
每个1G)。
导入SQLData.sql
现在,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!
试一试。如果您对此有其他疑问,请询问。相信我;这将在短期内和长期内发挥作用。
在步骤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并继续
关于在步骤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文章的位置。
Aug 27, 2012
:Proper tuning for 30GB InnoDB table on server with 48GB RAM Jan 17, 2013
:MySQL 5.5 - Innodb - innodb_log_file_size higher than 4GB combined? 就个人而言,我仍会采用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