会。myisam表级锁虽不直接计算耗cpu,但导致大量线程卡在locked状态,引发高频上下文切换(cs>50k/s),使mysqld进程cpu飙升至300%–500%,属调度型高cpu;确认需查engine字段、processlist中state=locked及info关联myisam表。

MyISAM表锁会导致CPU飙升吗?
不会。MyISAM的表级锁本身不直接导致CPU飙升,但会引发连锁反应:大量会话卡在Locked状态等待释放表锁,MySQL线程调度器持续轮询、唤醒、挂起这些阻塞线程,线程上下文切换开销剧增——在多核机器上,top里mysqld进程的CPU使用率可能飙到300%甚至500%,而实际SQL计算量极小。这是典型的“调度型CPU高”,不是“计算型CPU高”。
如何确认是MyISAM表锁而非InnoDB锁?
关键看三处:
-
SHOW ENGINE MYISAM STATUS—— MyISAM引擎没有这个命令,执行会报错,但SHOW TABLE STATUS LIKE 'table_name'能查出Engine字段是否为MyISAM -
SHOW FULL PROCESSLIST中State列出现大量Locked(注意不是Waiting for table metadata lock,后者是元数据锁,跟引擎无关) -
information_schema.TABLES里查ENGINE = 'MyISAM'的表,再结合PROCESSLIST中Info字段的SQL,确认操作的是否正是这些表
特别注意:State = Locked只出现在MyISAM写操作(INSERT/UPDATE/DELETE)期间,且只要有一个写请求,后续所有对该表的读写都会排队等待——哪怕只是SELECT也会被堵住。
为什么MyISAM锁问题在MySQL 8.0+更难察觉?
因为MySQL 8.0默认禁用MyISAM(disabled_storage_engines=MyISAM),但老系统迁移时可能残留MyISAM表,或应用显式指定ENGINE=MyISAM建表。这类表在performance_schema中几乎不暴露锁信息:data_locks、INNODB_LOCKS等视图对MyISAM完全无效;SHOW OPEN TABLES WHERE In_use > 0倒是可以看到哪些MyISAM表被打开且正在用,但无法区分是读还是写锁。
所以排查必须回归原始手段:
- 先用
SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'db_name' AND ENGINE = 'MyISAM';捞出全部MyISAM表 - 再用
SELECT * FROM information_schema.PROCESSLIST WHERE INFO LIKE '%table_name%' AND STATE = 'Locked';交叉验证 - 如果
Threads_running高但QPS低,且SHOW PROCESSLIST里Locked线程占多数,基本可锁定
临时止血和长期解法
止血不能只KILL一个线程——MyISAM是表级锁,当前持有锁的会话一杀,下一个排队的立刻拿到锁继续堵。正确做法是:
- 找到持有锁最久的那个会话:
SELECT * FROM information_schema.PROCESSLIST WHERE STATE = 'Locked' ORDER BY TIME DESC LIMIT 1;,记下ID - 确认它执行的是什么操作:
INFO字段是否是大事务(如LOAD DATA INFILE、全表UPDATE) - 如果业务允许,
KILL该ID;否则,优先改应用逻辑,把批量操作拆成小批次,或加LOW_PRIORITY降低写优先级
长期必须迁走:MyISAM不支持事务、崩溃恢复弱、并发能力差。哪怕只是读多写少的统计表,也建议换成InnoDB + READ COMMITTED隔离级别,配合覆盖索引避免锁升级。别信“MyISAM读快”——在现代SSD和足够innodb_buffer_pool_size下,InnoDB的读性能差距可以忽略,而锁可控性是质的区别。











