虽然标题是如何更换引擎,但面对大数据量级的表,执行任何表的更新操作(如修改字段类型)都要谨慎再谨慎。
如何更换引擎?
语句其实很简单,入门级别:
ALTER TABLE tbl ENGINE=InnoDB;
如果你的数据量级就几个G,也不担心短时间内的更新阻塞,看心情操作就好。
如果你的数据量级是几个T,那就得斟酌斟酌了。有一个很明显的问题:执行时间会很长。
大数据量级的表更新操作执行时间为什么长?
这是由执行原理所决定的:
当表执行更新操作时,MySQL会按行将数据从原表copy到一张新表,拷贝期间可能会耗尽系统的I/O(吞吐量),CPU可能会被打满,同时还会对原表加上只读锁。所以在有高频操作的表上执行此操作要特别小心,更新操作完成前会阻塞其他所有数据更新。
另外:
如果更换存储引擎,将失去原引擎的所有特性。若将InnoDB表转换为MyISAM,再转换回InnoDB,则原InnoDB表上的外键(MyISAM暂不支持外键)将会丢失。
替代方案1(安全但效率低):先导出再导入
先用mysqldump
命令将原表数据全部导出,删除导出的SQL文件最前面的DROP TABLE
一行,再修改CREATE TABLE
的存储引擎,同时修改表名加后缀比如_tmp
,最后使用source
命令导入。
导入完毕后,执行rename
命令,替换旧表。
替代方案2(较安全且高效):无需导出全表,借用INSERT…SELECT
导入
先创建一个新的存储引擎表,然后使用INSERT…SELECT
将旧表数据导入到新表。
CREATE TABLE innodb_tbl LIKE myisam_tbl;
ALTER TABLE innodb_tbl ENGINE=InnoDB;
INSERT INTO innodb_tbl SELECT * FROM myisam_tbl;
数据量不大的情况,可直接使用;如果数据量很大,可考虑分批处理:
分批处理时,建议对每一段数据执行事务提交,以避免事务太大产生过多的undo。
假设主键字段为id,重复执行以下语句:
START TRANSACTION;
INSERT INTO innodb_tbl SELECT * FROM myisam_tbl WHERE id BETWEEN 1 AND 1000;
COMMIT;
Tips
1、执行过程中可对原表加锁,以确保新表和原表的数据一致性。
2、如果不想阻塞原表,可借用触发器,将数据同步到新表。
3、亦可在代码层直接将数据同步于新旧两表。
4、如果数据量级较大使用以上方案时,需提前做容灾演练。
网友评论