LOCK TABLES 不适合常规 DML 场景,因其会隐式提交当前事务、绕过 InnoDB 行锁、阻塞并发且破坏事务边界;仅适用于 MyISAM 离线维护等极少数非事务性操作。

MySQL 的 LOCK TABLES 不适合常规 DML 场景,它只在极少数特定维护操作中可用,且与事务、InnoDB 行锁存在根本冲突。
为什么 LOCK TABLES 不能用于普通 DML 事务
LOCK TABLES 是一种显式、会话级的表级锁,它会强制断开当前会话的活跃事务(如果使用 InnoDB),并隐式执行 COMMIT。这意味着:
- 一旦执行
LOCK TABLES t1 WRITE,之前未提交的事务自动提交,无法回滚 - InnoDB 的行锁机制被绕过,所有后续 DML(如
UPDATE、DELETE)必须等锁释放,丧失并发能力 - MyISAM 表虽支持,但不支持事务,DML 无法回滚,错误风险高
- 其他会话对同一表的读写会被阻塞,容易引发锁等待甚至超时(
Lock wait timeout exceeded)
什么情况下还能用 LOCK TABLES?
仅限于非事务性、短时、离线维护类操作,例如 MyISAM 表的修复或全量数据导出前的一致性快照:
- 备份前锁定 MyISAM 表:
LOCK TABLES orders READ,然后mysqldump --skip-lock-tables配合使用(注意:READ 锁允许其他会话继续 SELECT,但禁止 DML) - 原子性替换临时表:
LOCK TABLES tmp_orders WRITE, orders WRITE,再执行RENAME TABLE tmp_orders TO orders,最后UNLOCK TABLES - 禁止任何写入的只读检查窗口(如核对统计值),但必须确保无长查询,否则会拖慢整个库
替代方案:该用什么做 DML 并发控制?
现代 MySQL 应用应完全避免 LOCK TABLES,改用更安全、细粒度的机制:
- InnoDB 默认行锁:普通
UPDATE、DELETE带 WHERE 条件时自动加行级记录锁,无需手动干预 - 显式加锁用
SELECT ... FOR UPDATE或SELECT ... LOCK IN SHARE MODE,在事务内安全控制读-写竞争 - 应用层幂等设计 + 唯一索引约束,比锁表更能防止重复提交
- 批量 DML 分批次执行,避免单语句长时间持有锁;监控
INFORMATION_SCHEMA.INNODB_TRX查看锁等待
最容易被忽略的坑
很多人以为 LOCK TABLES 能“保护数据不被修改”,却没意识到它本身就会破坏事务边界。最隐蔽的问题是:UNLOCK TABLES 不仅释放锁,还会隐式关闭当前会话的所有预处理语句(PREPARE),并重置会话级临时表和用户变量。如果你在锁表后依赖 @var 或 TEMPORARY TABLE,它们会在解锁瞬间失效——这个行为不会报错,但结果可能静默异常。


















