myisam 不会发生死锁,因其仅支持表级锁且无死锁检测机制;所谓“卡住”实为锁表等待,需通过 show processlist 等命令诊断;迁移到 innodb 是根本解决方式,但须谨慎执行并调优配置。

MyISAM 在高并发写操作下根本不会发生死锁,它只有表级锁等待;所谓“死锁”是误判,真实问题是写操作一来就锁全表,其他读写全部排队——这不是调参能解决的,必须换引擎。
MyISAM 根本没有死锁机制,别查 SHOW ENGINE INNODB STATUS
MyISAM 不支持事务、不维护锁队列、也没有死锁检测。你在它上面看到的“卡住”,全是 Locked 或 Waiting for table level lock 状态,查 SHOW ENGINE INNODB STATUS 永远为空。真正该看的是:
-
SHOW PROCESSLIST:找 State 为Locked的线程 -
SHOW OPEN TABLES WHERE In_use > 0:确认哪些表正被写锁强占 -
SHOW STATUS LIKE 'Table_locks_waited':数值持续上涨,说明锁争用严重
ALTER TABLE ENGINE=InnoDB 不是“优化”,而是迁移前提
直接执行 ALTER TABLE tbl_name ENGINE=InnoDB 很可能失败或引发风险,必须提前检查:
- 磁盘空间是否足够:转换过程会先建新表再拷数据,临时空间至少等于原表大小
- 主键是否显式存在:InnoDB 强依赖聚簇索引,没主键会用隐藏
ROW_ID,导致二级索引膨胀、查询变慢 - 全文索引是否在用:MySQL 5.6 以前的 InnoDB 不支持
FULLTEXT,若业务强依赖,得确认版本 ≥ 5.7 - 外键是否启用:MyISAM 不支持外键,但迁入 InnoDB 后若加了外键约束,需确保关联表也已是 InnoDB
大表别直接 ALTER,用 pt-online-schema-change 或 gh-ost 在线改;小表也避开业务高峰。
InnoDB 行锁优势要靠配置激活,不是换完就自动生效
换完引擎后如果并发写还是卡,大概率是默认配置太保守:
-
innodb_buffer_pool_size至少设为物理内存的 50%–75%,太小会导致频繁刷脏页,抵消行锁价值 -
innodb_log_file_size建议单个 ≥ 256M(如innodb_log_file_size = 512M),增大可减少 checkpoint 频率 -
innodb_flush_log_at_trx_commit = 2可显著提升吞吐(每秒刷一次日志),但崩溃时最多丢 1 秒事务 -
innodb_thread_concurrency = 0(默认)别乱改成非零值,反而可能成为调度瓶颈
innodb_lock_wait_timeout 默认 50 秒,只是超时抛错时间,不是锁粒度控制参数——调小它不会减少锁,只会让报错更快。
真正容易被忽略的是:MyISAM 的“锁表”问题本质是设计缺陷,任何 SQL 优化、LOW_PRIORITY、分批插入都只能缓解表象;只要还在用 MyISAM,就永远绕不开全表阻塞这个硬伤。











