MyISAM在多线程高频更新下吞吐量必然暴跌,因其仅支持表级锁,任何UPDATE/DELETE都会对整表加排他锁,导致读写全阻塞;并发写入彻底串行化,Table_locks_waited占比超10%即属严重;日志表混入SELECT会压垮写入;根本解法是迁移到InnoDB,而非调优MyISAM。

MyISAM 吞吐量在多线程高频更新下必然暴跌,不是配置没调好,而是它根本没设计成干这事的。
MyISAM 表级锁让所有写请求排队等一把锁
MyISAM 对整张表加排他锁(X lock),哪怕你只 UPDATE 一行,整个表就不可读不可写。多线程并发写时,线程全卡在 Waiting for table level lock 状态——不是慢,是彻底串行化。
- 现象:
SHOW STATUS LIKE 'Table_locks_waited'持续上涨,且Table_locks_waited / (Table_locks_immediate + Table_locks_waited)超过 10% 就已严重 - 对比 InnoDB:
SELECT COUNT(*) FROM information_schema.INNODB_TRX可能有几十个活跃事务,但互不阻塞;MyISAM 下同一张表只能有一个写事务在跑 - 哪怕用
concurrent_insert = 2,也只对尾部追加 INSERT 有效;一旦混入任何UPDATE、DELETE或REPLACE,锁立刻升级为全表阻塞
日志类表混 SELECT 查询会直接压垮写入能力
MyISAM 的表级锁不区分读写:一个 SELECT COUNT(*) FROM log_table 正在执行,所有 INSERT 都得干等。日志表本该只写不读,但监控拉取、后台统计、临时排查常偷偷加上读操作。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 禁止在 MyISAM 日志表上执行任何
SELECT:包括COUNT、MAX(id)、GROUP BY、甚至EXPLAIN - 替代方案必须物理隔离:把读需求迁到汇总表(按小时预聚合)、Elasticsearch、或用
SELECT ... INTO OUTFILE导出后离线分析 -
INSERT DELAYED已在 MySQL 5.6+ 彻底移除,任何残留代码都会报错ERROR 1064 (42000),别试
高并发下空洞碎片反而加剧锁争抢
MyISAM 删除数据后留下空洞,concurrent_insert = 2 允许继续往文件末尾追加,但前提是“没有其他写操作干扰”。而高频更新场景中,OPTIMIZE TABLE 常被误用为“清理碎片”手段——它会重建整个数据文件,期间全表锁死,且重建后空洞清零,concurrent_insert = 2 效果反而暂时失效。
-
concurrent_insert = 2必须写进my.cnf并重启 MySQL;SET GLOBAL动态设置无效 -
OPTIMIZE TABLE只建议夜间低峰期运行,且不能频繁执行(比如每天多次) - 真正稳定的写入路径只有:纯追加 INSERT + 无任何 SELECT/UPDATE/DELETE 干扰 +
concurrent_insert = 2硬编码生效
最常被忽略的一点是:当吞吐量跌到无法接受时,问题从来不在“怎么让 MyISAM 更快”,而在于“为什么还在用 MyISAM”。只要业务需要多线程同时修改同一张表,InnoDB 就是唯一合理选项——不是因为它更好,而是 MyISAM 根本不支持这个场景。










