题
我有一个数据库,其整体大小约为44GB,其中IBDATA1为〜35GB。这是没有意义的,因为数据的大小不应超过10GB。
我使用以下查询来获取数据大小:
SELECT CONCAT(table_schema, '.', table_name),
CONCAT(ROUND(table_rows / 1000000, 2), 'M') rows,
CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G') DATA,
CONCAT(ROUND(index_length / ( 1024 * 1024 * 1024 ), 2), 'G') idx,
CONCAT(ROUND(( data_length + index_length ) / ( 1024 * 1024 * 1024 ), 2), 'G') total_size,
ROUND(index_length / data_length, 2) idxfrac
FROM information_schema.TABLES
ORDER BY data_length + index_length DESC
LIMIT 30;
有什么想法如何清洁ibdata1,为什么它会变得如此呢?
顺便说一句,我使用innodb_file_per_table
解决方案
安德烈亚斯(Andreas)首先就做什么. 。 +1 for andreas !!!
我想澄清为什么这个答案是唯一的方法和方法。
默认情况下,IBDATA1通常包含四种类型的信息
- 表数据
- 表索引
- MVCC(多离子并发控制)数据
- 表元数据
在存储IbData1的InnoDB表上运行优化表将使情况变得更糟,因为这就是它的作用:
- 使表的数据和索引在IBDATA1中连续
- 它使ibdata1生长,因为连续数据附加到ibdata1
您可以将表数据和表索引从IBDATA1隔离,并使用 innodb_file_per_table. 。这样,只有MVCC和表格元数据才能存在于Ibdata1中。
如果您已经使用了它,那么您必须拥有一个高写的环境,该环境存储大量MVCC以支持交易隔离。一旦完成了MVCC的交易,该空间就被放弃了以重复使用。
要缩小一劳永逸的ibdata1,您必须执行以下操作:
步骤01)MySQLDUMP所有数据库中的所有数据库中
步骤02)删除所有数据库(MySQL模式除外)
步骤03) service mysql stop
步骤04)将以下行添加到/etc/my.cnf
[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G
Sidenote:无论您为Innodb_buffer_pool_size设置什么设置,请确保Innodb_log_file_size是Innodb_buffer_pool_size的25%。
步骤05) rm -f /var/lib/mysql/ibdata1 /var/lib/mysql/ib_logfile
此时,/var/lib/mysql中只有MySQL模式
步骤06) service mysql start
这将在10MB,ib_logfile0和ib_logfile1处重新创建ibdata1
步骤07)重新加载sqldata.sql到mysql
ibdata1将增长,但仅包含表元数据
每个InnoDB表都将存在于Ibdata1之外
假设您有一个InnoDB表,名为mydb.mytable。如果您进入/var/lib/mysql/mydb,您将看到两个代表表的文件
- mytable.frm(存储引擎标头)
- mytable.ibd(mydb.mytable的表数据和表索引的故乡)
IBDATA1将永远不会包含InnoDB数据和索引。
使用innodb_file_per_table在/etc/my.cnf中,您可以运行 OPTIMIZE TABLE mydb.mytable;
File/var/lib/mysql/mydb/mytable.ibd实际上会收缩。
我想建议您一个公式,以查询我的帖子中的InnoDB缓冲池尺寸 InnoDB和Myisam之间的主要区别是什么?
其他提示
我最好的猜测是,它在某个时间点很大。
IBDATA1永远不会收缩,因此它将保持其最大尺寸。也许您已经有几个桌子,然后才完成innodb_file_per_table。
我知道缩小它的唯一方法是进行转储,删除文件(IBDATA,IBLOG和ALL .IDB)并加载转储。