mysql - 将大型 MyISAM 表转换为 InnoDB

标签 mysql innodb myisam large-data

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

我试过了:

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

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

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

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

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

  • INSERT INTO ... SELECT * FROM - 创建了相同结构的表并进行了尝试。在几百万行之后也会减慢然后超时。 (感谢@Ernestas Stankevič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

最佳答案

innodb_buffer_pool_size=2G 对于 4GB 的机器来说可能是危险的高。试试1500M。交换内存或用完内存比拥有小缓存更糟糕。

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

您运行的是什么版本的 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 或更高版本,请一次添加一个。

关于mysql - 将大型 MyISAM 表转换为 InnoDB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35741063/

相关文章:

mysql - MySQL 中具有并集的相同 CASE 条件的多个 THEN

javascript - 使 Alexa Skill Loop 成为语音功能

Cron 作业中的 MySQL 事务

如果需要的话,MySQL 存储过程要 INSERT DELAYED 但先 CREATE TABLE 吗?

php - 如何防止 PHP 中的 SQL 注入(inject)?

javascript - 如何使用 Sequelize.js 获取 MAX(id) GROUP BY 其他字段?

mysql - 当主线程状态为 "making checkpoint"时,mysql 实际上在做什么?

mysql - AWS RDS 可用内存和交换空间使用量较低

sql - MySQL 返回不正确的数据?

mysql - InnoDB 查询持续时间不一致