将大型MyISAM表转换为InnoDB

时间:2016-03-02 07:34:18

标签: mysql innodb myisam large-data

我有一个MyISAM表(10M行,3.5G,计划达到~80M),我总是无法将其转换为InnoDB。

我试过了:

  • ALTER TABLE - 2分钟后失去联系。也许我做错了。

  • mysqldump - 尝试创建转储,然后将ENGINE=MyISAM更改为ENGINE=InnoDB

它开始很好但随着新表中行数的增长(~3M),它变得越来越慢,最后几个小时后它超时(--reconnect为ON)。

如果我将缓冲池大小增加到2G,它会在更多行(~6M)之后变慢但是机器用完了RAM。

在转储恢复期间的SHOW PROCESSLIST中,我看到许多查询在“查询结束”状态下停留了2-3分钟。从google-ing无法理解这是什么意思。

  • INSERT INTO ... SELECT * FROM - 创建了相同结构的表并尝试了这一点。在数百万行之后也会减速然后超时。 (感谢@ErnestasStankevičius提醒我这件事。)

服务器:

Aws EC2 4GB Ubuntu14.04

my.cnf

wait_timeout=28800
connect_timeout=28800
innodb_lock_wait_timeout=28800
net_read_timeout=7200
net_write_timeout=7200
innodb_buffer_pool_size=1G
innodb_io_capacity=100 /*200 is heavy on the machine*/
innodb_flush_log_at_trx_commit=0
reconnect=1

2 个答案:

答案 0 :(得分:2)

对于4GB的机器来说,{p> innodb_buffer_pool_size=2G可能危险地高。试试1500M。交换内存或耗尽内存比使用小缓存更糟糕。

从mysql命令行工具运行ALTER,而不是某些UI。 (用户界面可能有你要达到的时间限制。

您运行的是哪个版本的MySQL?你有多少指数?请告诉我们SHOW CREATE TABLE。删除所有辅助密钥,仅保留PRIMARY KEY。转换后添加其他索引; 5.6或后者可以做到“就地”。

如果您没有PRIMARY KEY,请创建一个; InnoDB确实需要一个。

这可能涵盖了大多数情况:

CREATE TABLE new LIKE real;
ALTER TABLE new ENGINE=InnoDB,
    DROP ..., -- all the secondary keys
    ADD PRIMARY (...), -- if needed
    ENGINE=InnoDB;
INSERT INTO new (...)
    SELECT ... FROM real ORDER BY ... -- insert in PK order
ALTER TABLE new
    ADD index ...;  -- rebuild secondary key(s) (see note)
RENAME TABLE real TO old, new TO real;
DROP TABLE old;

注意:如果您运行的是5.5或更早版本,请在一个ALTER中添加所有辅助密钥。如果您运行的是5.6或更高版本,请一次添加一个。

答案 1 :(得分:1)

我的解决方案是从新的(InnoDB)表结构中删除一些索引,然后添加数据 我使用INSERT new_table SELECT * FROM old_table复制数据

您删除的索引越多 - 数据进入的速度就越快。

之后,我重新创建了索引 感谢@ i486。