此查询中的SELECT ... FOR UPDATE
是否锁定此表中的行?
表在InnoDB中,查询在内部交易
select max(id) from table1 FOR UPDATE
我有这段代码,似乎SELECT ... FOR UPDATE
没有锁定行。
答案 0 :(得分:2)
SELECT ... FOR UPDATE
阻止其他会话执行SELECT ... LOCK IN SHARE MODE
改为使用SELECT ... LOCK IN SHARE MODE
在行上设置共享模式锁定 读。共享模式锁启用其他 会话来读取行而不是 修改它们。读取的行是 最新的,如果他们属于 还没有的另一笔交易 已提交,读取块直到那个 交易结束。
请参阅docs。
答案 1 :(得分:1)
select id from table where id IN (select max(id) from table1) FOR UPDATE
答案 2 :(得分:1)
我也偶然发现了这个问题并进行了测试。
CREATE TABLE `test1` (
`user_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`ds_id` mediumint(8) unsigned NOT NULL,
`producer_id` mediumint(8) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`user_id`,`ds_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `test1` VALUES
(3, 4, 2),
(17, 1, 1),
(18, 1, 9);
线程1:
begin;
select max(ds_id) from test1 where user_id=3 for update;
+------------+
| max(ds_id) |
+------------+
| 3 |
+------------+
线程2:
begin;
select max(ds_id) from test1 where user_id=3 for update;
... waiting ...
线程1:
insert into test1 set user_id=3, ds_id=4, producer_id=1;
commit;
线程2:
+------------+
| max(ds_id) |
+------------+
| 3 |
+------------+
使用组功能时,InnoDB不会锁定间隙,而只是锁定现有记录。如果没有组功能,线程2将按预期返回2行,包括全新的行。
答案 3 :(得分:0)
SELECT MAX(id) FROM table1 FOR UPDATE
- 不会锁定任何行,因为它实际上并不扫描任何行。从表索引中检索所需信息。
如果您在查询前加DESCRIBE
,则显示:
# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
'1', 'SIMPLE', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'Select tables optimized away'
SELECT id FROM table1 WHERE id = (SELECT MAX(id) FROM table1) FOR UPDATE
- 将锁定与MAX(id)
匹配的一行,因为您明确检索了该行。
SELECT id FROM table1 ORDER BY id DESC LIMIT 1 FOR UPDATE
- 将使用MAX(id)
和ORDER BY
的组合锁定所有行并检索LIMIT 1
。
这将再次由DESCRIBE
查询解释。
答案 4 :(得分:-2)
与Oracle文档中一样 本条款受以下限制: 您不能使用以下其他构造指定此子句:DISTINCT运算符,CURSOR表达式,集合运算符,group_by_clause或聚合函数。