MySql 5.7 中的行锁有限制吗?
Is there a limit for row lock in MySql 5.7?
我在 MySql 5.7 中遇到一个问题,当我 select 14 行或更多行带有 FOR UPDATE 时,整个 table 被锁定。即使我 select 他们通过主键(所以,它是索引和唯一的)。从字面上看,它看起来像这样。当我 运行 这个查询时:
select * from mytable
where id in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
for update;
一切正常,只有 selected 行被锁定。但是这个查询:
select * from mytable
where id in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
for update;
锁定整个 table。我无法更新任何其他条目,也无法插入新行。 table 已锁定。 ID 可以不同,重要的是它们的数量(14 个或更多)。我试图 google 但没有找到任何东西。
是否对行锁(13 行)有一些严格的 MySql(我们使用 5.7 版)限制,如果您 select 多则应用 table 锁?它可以以某种方式改变吗?或者这只是我们的具体问题,我们需要深入挖掘?
看来没有人知道真正的原因。好吧,那么我可以 post 我们最终得出的解决方案。
我们使用了临时 table,它仅包含一列 id
,我们在其中插入了所有必需的 ID,然后将其与我们的 table 而不是 IN
子句连接:
CREATE TEMPORARY TABLE if not exists tmp (id int primary key);
truncate tmp;
INSERT INTO tmp VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15);
select t.* from mytable t
join tmp on tmp.id = t.id
for update;
这样一来,无论我们传递多少个 ID,都只会锁定指定的行。不过还是有一些问题。
首先,如果我们使用 engine=memory
,由于某种原因,这个技巧不起作用。此外,如果我们使用 select
而不是 values
将值插入到临时 table 中,进一步的 select for update
仍然会在一定数量的 id 处锁定整个 table。但在后一种情况下,可以通过在插入后立即调用 optimize table tmp;
来解决问题(当我们使用 engine=memory
时它仍然没有帮助)。
所以,就是这样。希望这会对某人有所帮助。
我在 MySql 5.7 中遇到一个问题,当我 select 14 行或更多行带有 FOR UPDATE 时,整个 table 被锁定。即使我 select 他们通过主键(所以,它是索引和唯一的)。从字面上看,它看起来像这样。当我 运行 这个查询时:
select * from mytable
where id in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
for update;
一切正常,只有 selected 行被锁定。但是这个查询:
select * from mytable
where id in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)
for update;
锁定整个 table。我无法更新任何其他条目,也无法插入新行。 table 已锁定。 ID 可以不同,重要的是它们的数量(14 个或更多)。我试图 google 但没有找到任何东西。
是否对行锁(13 行)有一些严格的 MySql(我们使用 5.7 版)限制,如果您 select 多则应用 table 锁?它可以以某种方式改变吗?或者这只是我们的具体问题,我们需要深入挖掘?
看来没有人知道真正的原因。好吧,那么我可以 post 我们最终得出的解决方案。
我们使用了临时 table,它仅包含一列 id
,我们在其中插入了所有必需的 ID,然后将其与我们的 table 而不是 IN
子句连接:
CREATE TEMPORARY TABLE if not exists tmp (id int primary key);
truncate tmp;
INSERT INTO tmp VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12), (13), (14), (15);
select t.* from mytable t
join tmp on tmp.id = t.id
for update;
这样一来,无论我们传递多少个 ID,都只会锁定指定的行。不过还是有一些问题。
首先,如果我们使用 engine=memory
,由于某种原因,这个技巧不起作用。此外,如果我们使用 select
而不是 values
将值插入到临时 table 中,进一步的 select for update
仍然会在一定数量的 id 处锁定整个 table。但在后一种情况下,可以通过在插入后立即调用 optimize table tmp;
来解决问题(当我们使用 engine=memory
时它仍然没有帮助)。
所以,就是这样。希望这会对某人有所帮助。