MySQL 行级锁

3

我不确定行级锁是如何工作的,但这是我的问题。我有一个表 T(id int,balance int)(engine = InnoDB),我想锁定 ID = 1 的行,所以我像这样开始了一个事务:

start transaction ; 
select * from T where ID = 1 FOR UPDATE ; 

在提交之前,我想尝试一下是否真的锁定了行。所以我启动了另一个会话并输入了以下内容:
UPDATE T set balance = balance  + 100 where ID = 1 ;

我清楚地看到我在等待锁定(30秒后超时)。

但是当我键入:

UPDATE T set balance = balance  + 8500 where ID = 2 ;

我也在等待锁定,那么如何只锁定ID = 1的行而不是整个表呢?

ID列上有索引吗? - Barmar
不,这很重要吗? - Lilo
2
是的。它锁定了所有必须读取以执行查询的行。如果该列没有建立索引,则必须读取表中的所有行才能找到其中“ID = 1”的行,并在读取每一行时将其锁定。当该列被索引时,它不需要扫描整个表(实际上锁定是在索引中实现的)。 - Barmar
1个回答

8
您需要在 id 列上添加索引,以确保获得行级锁。 SELECT ... FOR UPDATE 锁定所有读取以执行查询的行,而不仅仅是实际选择的行。如果没有索引,则必须执行全表扫描,因此每一行都会被锁定。
有了索引,它只需在该索引条目中放置一个锁定,无需读取任何其他行,因此不会锁定任何其他行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接