锁定查询结果 LOCK IN SHARE MODE
SELECT ... LOCK IN SHARE MODE 用于在查询数据时获取共享锁,防止其他事务对数据进行写操作,但允许其他事务对数据进行读操作。即使用该语句时,会在读取的数据行上设置共享模式锁定,其他会话可以读取这些行,但在当前事务提交之前其他事务不能对其进行修改。
提示
seekdb 模拟了 LOCK IN SHARE MODE 共享锁语法的功能,使用写锁来实现,这样可以满足一些软件的兼容性需求,同时保证语法的正确性。由于使用写锁会使添加了 LOCK IN SHARE MODE 命令的读操作之间相互阻塞,因此一般不建议使用该语法,特别是在性能敏感的场景中更应该避免使用。
本文通过示例介绍如何使用 SELECT ... LOCK IN SHARE MODE 锁定查询结果。
示例
-
在 会话 1 中,执行下面 SQL 语句开启事务。
START TRANSACTION; -
在 会话 1 中,使用
LOCK IN SHARE MODE语法在表test_tbl1中对id值等于1的记录进行查询,并获取共享锁。SELECT * FROM test_tbl1 WHERE id = 1 LOCK IN SHARE MODE;返回结果如下:
+------+------+
| id | name |
+------+------+
| 1 | A1 |
+------+------+
1 row in set -
在 会话 2 中,执行下面 SQL 语句开启事务。
START TRANSACTION; -
在 会话 2 中,执行下面 SQL 语句查询表
test_tbl1中id值等于1的记录。SELECT * FROM test_tbl1 WHERE id = 1;返回结果如下:
+------+------+
| id | name |
+------+------+
| 1 | A1 |
+------+------+
1 row in set -
在 会话 2 中,执行下面 SQL 语句在表
test_tbl1中id值等于1的行对应的 name 的改为 'A1A1A1'。该 SQL 语句会等待,直到 会话 1 的事务回滚或者COMMIT才得到执行。UPDATE test_tbl1 SET name = 'A1A1A1' WHERE id = 1;返回结果如下:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction -
在 会话 1 中,执行下面 SQL 语句提交事务。
COMMIT; -
在 会话 2 中,再次执行 步骤 4 的更新语句。
UPDATE test_tbl1 SET name = 'A1A1A1' WHERE id = 1;返回结果如下:
Query OK, 1 row affected
Rows matched: 1 Changed: 1 Warnings: 0