You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

REPEATABLE-READ隔离级别下LOCK TABLES WRITE阻塞SELECT的原因咨询

问题描述

当前处于REPEATABLE-READ隔离级别,原本以为任何隔离级别下的所有SELECT操作都是非阻塞的,但遇到了如下场景:

会话1操作

mysql> lock tables users write;
Query OK, 0 rows affected (0.00 sec)

会话2操作

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from users where id = 1; // 这里一直等待

直到会话1执行解锁:

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

会话2的SELECT才返回结果:

mysql> select * from users where id = 1;
+----+-----------------+--------------------+------+---------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+------------+
| id | name            | email              | rol  | email_verified_at   | password                                                     | remember_token | created_at          | updated_at          | deleted_at |
+----+-----------------+--------------------+------+---------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+------------+
|  1 | Bella Lueilwitz | orlo19@example.com | NULL | 2022-08-01 17:22:29 | $2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi | MvMlaX9TQj     | 2022-08-01 17:22:29 | 2022-08-01 17:22:29 | NULL       |
+----+-----------------+--------------------+------+---------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+------------+
1 row in set (10.51 sec)

这和之前看到的一个场景相反,想知道自己忽略了什么?


问题解答

你混淆了MySQL服务器层的表级锁和InnoDB存储引擎的行级锁/事务隔离级别这两个完全不同的锁机制:

  1. LOCK TABLES ... WRITE是服务器层的排他表锁
    一旦某个会话执行LOCK TABLES users WRITE,会获取该表的独占排他锁,此时MySQL服务器会直接拦截其他所有会话对该表的任何读写请求——不管你用什么事务隔离级别,也不管是行级查询还是全表查询,都会被阻塞直到锁释放。这是服务器层面的全局锁,优先级远高于存储引擎的行级锁。

  2. 你之前的认知误区
    你以为“任何隔离级别下SELECT都非阻塞”,这个结论只适用于InnoDB行级锁场景:比如在REPEATABLE-READ级别下,普通SELECT用快照读(MVCC),不会被行级写锁阻塞。但这个规则完全不适用于服务器层的表级锁,因为表级锁直接阻断了整个表的访问路径,根本轮不到存储引擎的MVCC逻辑生效。

  3. 关于你提到的相反场景
    那个场景大概率存在特殊前提:比如操作的是MyISAM引擎(但MyISAM写锁同样会阻塞读)、会话未正确持有锁、或者使用了特殊的读语法(比如SELECT ... /*+ SKIP_LOCKED */这类跳过锁的扩展语法),但默认情况下LOCK TABLES ... WRITE必然会阻塞其他会话的SELECT,你的实际测试结果才是符合MySQL标准行为的。

内容的提问来源于stack exchange,提问作者user19551894

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:15:25