MySQL(InnoDB引擎)中,执行UPDATE
语句时的锁策略如下:
一、什么时候锁行?
使用索引条件进行更新时,InnoDB只锁定涉及到的具体行,使用的是行锁。
示例:
-- id为主键或有索引
UPDATE table_name SET column='value' WHERE id=100;
特点:
锁定具体一行或多行,不影响其他行并发访问。
如果使用索引定位记录高效且准确,InnoDB默认都使用行锁。
二、什么时候锁表?
以下几种情况下,可能会升级为表锁或造成类似表锁的效果:
更新语句的条件列无索引
-- name字段未建立索引
UPDATE table_name SET column='value' WHERE name='张三';
此时InnoDB无法快速定位记录,会扫描整张表,产生范围锁(Gap锁)甚至全表锁,影响并发性。
范围更新时,可能产生范围锁(Gap锁)
-- 范围更新,id有索引
UPDATE table_name SET column='value' WHERE id BETWEEN 10 AND 100;
这种情况会产生Gap锁,锁定一定范围的记录,阻塞部分范围的并发插入或修改操作,可能导致性能下降(但不是严格的表锁)。
更新的行数比例非常大
虽然InnoDB通常不会自动将行锁升级成表锁,但如果一次更新几乎涉及全部记录,则表现类似于表锁,对并发性能有明显影响。
显式表锁
执行
LOCK TABLES table_name WRITE;
时明确要求表锁。
三、如何避免锁表?
条件字段添加索引,确保更新时快速精确定位记录。
避免大范围或模糊条件的更新操作。
四、总结(简洁版)
因此,在业务场景中,务必保证UPDATE
的条件字段拥有索引,避免产生意外的表级锁竞争。