mysql表锁与行锁各有什么优缺点_mysql性能对比分析

来源:这里教程网 时间:2026-02-28 20:52:10 作者:

表锁为什么快但并发差?关键看加锁粒度

表锁直接锁整张表,MySQL不用查索引、不定位行,所以

加锁快、开销小
。MyISAM默认就用它,
不会死锁
——因为锁的只有“表”这个单一资源,事务间不存在交叉等待链。但代价也很直接:哪怕两个UPDATE改的是完全不同的行,只要操作同一张表,就得排队。

读锁(
LOCK TABLES t READ
):其他事务还能读,但所有写操作(INSERT/UPDATE/DELETE)全部阻塞
写锁(
LOCK TABLES t WRITE
):其他事务连SELECT都不让,彻底串行化
典型陷阱:在InnoDB里执行
UPDATE
没走索引(比如
WHERE name = 'xxx'
name
无索引),InnoDB会自动退化为表锁——你以为是行锁,实际已拖垮并发

行锁真能并发高?前提是SQL必须走索引

InnoDB的行锁本质是“锁索引项”,不是锁物理行。这意味着:只有

WHERE
条件命中索引(主键、唯一索引、普通索引均可),才能真正锁住几行;否则就是全表扫描+表级锁。

正确示例:
UPDATE user SET balance = 100 WHERE id = 123
id
是主键)→ 锁单行
危险示例:
UPDATE user SET balance = 100 WHERE status = 'pending'
status
无索引)→ 锁整张表
注意间隙锁:
WHERE id > 10 AND id 这类范围查询,InnoDB还会锁住(10,20)之间的“间隙”,防止幻读——这属于行锁的延伸行为,不是额外加锁,但会影响并发插入

怎么判断当前是不是被表锁卡住了?看这两个状态值

当应用突然变慢、UPDATE/INSERT大量超时,先别急着查慢SQL,先确认是否陷入表锁争抢:

SHOW STATUS LIKE 'table_locks%';
table_locks_immediate
:立刻获得表锁的次数(健康值应远高于另一项)
table_locks_waited
:因表锁等待的次数;如果该值持续增长,说明存在严重表级锁竞争
补充检查:
SHOW OPEN TABLES WHERE In_use > 0;
可看到哪些表正被显式锁定(
FLUSH TABLES WITH READ LOCK
LOCK TABLES
导致)

InnoDB里什么时候该主动用表锁?别迷信“行锁一定更好”

行锁不是银弹。在某些场景下,表锁反而更稳、更可控:

批量导入数据前:
LOCK TABLES t WRITE
,避免其他事务干扰,比逐行加X锁开销低得多
维护性操作(如
OPTIMIZE TABLE
ALTER TABLE
加索引):这些DDL本身就会触发MDL写锁,再叠加行锁只会增加死锁概率
小表高频更新:比如配置表
sys_config
只有10行,InnoDB行锁管理成本可能反超表锁——此时
SELECT ... FOR UPDATE
不如直接
LOCK TABLES
干净

最常被忽略的一点:锁的选择从来不是“引擎决定”的,而是由SQL写法、索引设计、事务隔离级别共同决定的。一个没走索引的

SELECT ... FOR UPDATE
,在InnoDB里照样变成表锁——代码没写错,但效果和MyISAM一样。

相关推荐