一个时代的终结
MyISAM 已被正式弃用。这并不令人意外——多年来这一点已经很明显。但这一次,它被写入了 MariaDB / MySQL 源代码中:MyISAM 引擎被标记为弃用,而内部使用它的最后堡垒也已完成迁移。
mysql 系统数据库(存储用户、权限、授权表的那个)不再使用 MyISAM。内部临时表也不再使用。在生产环境中容忍 MyISAM 的最后两个借口已经消失了。
为什么 MyISAM 存活了这么久
要理解当前的情况,我们需要回顾 MyISAM 的历史及其在生态系统中的角色。
MyISAM 是 MySQL 5.5(2010 年)之前的默认存储引擎。十多年来,它是数百万 Web 应用程序的默认选择。WordPress、Joomla、Drupal、phpBB ——所有这些应用程序都是主要使用 MyISAM 开发和测试的。
MyISAM 在当时的优势是真实的:
- 简单性:一个
.MYD文件存储数据,一个.MYI文件存储索引。易于备份,易于移动。 - 读取性能:对于读密集型工作负载(博客、展示网站),MyISAM 很快。
- 全文搜索:MyISAM 在 InnoDB 之前很久就支持全文搜索。
- 低内存占用:MyISAM 使用很少的内存,这在 512 MB 服务器的时代至关重要。
但这些优势已经成为历史遗迹。InnoDB 现在提供了所有这些功能,而且远远不止。
为什么你必须现在迁移
没有事务支持
MyISAM 不支持 ACID 事务。没有 BEGIN,没有 COMMIT,没有 ROLLBACK。每条语句都是自动提交的。如果在写入过程中发生崩溃,你的数据会处于不确定状态。
没有行级锁
MyISAM 使用表级锁。一次写入会锁定整个表,阻塞所有其他读写操作。使用 InnoDB,锁定发生在行级别,实现并发。
没有外键
MyISAM 不支持外键约束。没有数据库级别的引用完整性。你完全依赖应用程序来维护数据一致性。
频繁损坏
MyISAM 表出了名的脆弱。服务器突然关闭、磁盘已满、对 mysqld 进程执行 kill -9 ——你的表就损坏了。myisamchk 和 REPAIR TABLE 成了你最好的朋友,但它们不是万能的。
没有活跃开发
这可能是最重要的论点。没有人再开发 MyISAM 了。没有错误修复,没有性能优化,没有新功能。它是冻结的代码,持续积累技术债务。
迁移:比你想的更简单
好消息是,从 MyISAM 迁移到 InnoDB 通常很简单。
识别 MyISAM 表
SELECT table_schema, table_name, engine, table_rows,
ROUND(data_length / 1024 / 1024, 2) AS data_mb
FROM information_schema.tables
WHERE engine = 'MyISAM'
AND table_schema NOT IN ('mysql', 'information_schema',
'performance_schema', 'sys')
ORDER BY data_length DESC;
转换一张表
ALTER TABLE mydb.mytable ENGINE = InnoDB;
就这么简单。MariaDB / MySQL 用 InnoDB 引擎重建表。索引被重新创建,数据被复制。对于小表,这是瞬间完成的。对于大表,可能需要几分钟。
注意事项
迁移过程中需要注意一些特殊情况:
全文表:如果你在 MyISAM 上使用 FULLTEXT 索引,好消息是——InnoDB 自 MySQL 5.6 / MariaDB 10.0 起就支持 FULLTEXT 索引了。语法完全相同。
MERGE 表:如果你使用 MERGE 引擎(多个 MyISAM 表的联合),你需要重新思考你的架构。InnoDB 分区或视图是替代方案。
*无 WHERE 的 COUNT()*:MyISAM 存储精确的行数,使得 `SELECT COUNT() FROM table是即时的。InnoDB 必须扫描索引。如果你的应用程序频繁执行无条件COUNT(*)`,你会注意到差异(对于百万行以下的表来说差异很小)。
磁盘空间:InnoDB 对于相同数据使用的磁盘空间比 MyISAM 多(平均多 1.5 到 2 倍),主要是由于 MVCC 和事务管理。在迁移前检查你的可用空间。
批量迁移脚本
对于拥有许多 MyISAM 表的数据库,这里有一个系统化的方法:
-- 生成 ALTER TABLE 命令
SELECT CONCAT('ALTER TABLE `', table_schema, '`.`', table_name,
'` ENGINE=InnoDB;') AS migration_sql
FROM information_schema.tables
WHERE engine = 'MyISAM'
AND table_schema NOT IN ('mysql', 'information_schema',
'performance_schema', 'sys')
ORDER BY data_length ASC;
从最小的表开始以验证流程,然后处理较大的表。
迁移之后
当所有表迁移到 InnoDB 后,建议进行一些配置调整:
# my.cnf
[mysqld]
default_storage_engine = InnoDB
innodb_buffer_pool_size = 70% # 可用内存的 70%
innodb_log_file_size = 256M # 或根据负载调大
innodb_flush_log_at_trx_commit = 1 # 完全持久性
并禁用你不再需要的 MyISAM 功能:
skip-external-locking
key_buffer_size = 8M # 最小值,用于剩余的系统表
结论
MyISAM 已被弃用。这不再是一种观点;这是一个技术事实。系统数据库已迁移,临时表已迁移,代码处于维护模式,没有未来。
如果你的生产环境中仍有 MyISAM 表,迁移的时候就是现在。转换很简单,收益是立竿见影的(事务、行级锁、崩溃恢复),而继续留在 MyISAM 上的风险只会越来越大。
ALTER TABLE ... ENGINE=InnoDB; ——这是你本周将执行的最好的查询。
本文最初发表于 Medium。
评论 (0)
暂无评论。
发表评论