select for update是锁定整个表还是仅锁定返回的行?

时间:2014-07-17 01:55:38

标签: mysql sql transactions locking row

我的表:

mysql> select * from users;
    +-----+---------+--------+
    | id  | name    | locked |
    +-----+---------+--------+
    |  10 | 1010    |      0 |
    |  11 | xxx     |      0 |
    | 888 | 888     |      0 |
    | 890 | qqq     |      0 |
    | 891 | qqq     |      0 |
    +-----+---------+--------+
CREATE TABLE `NewTable` (
`id`  int NOT NULL ,
`name`  varchar(255) NULL ,
`locked`  tinyint NULL DEFAULT 0 ,
PRIMARY KEY (`id`)
);

交易1(在终端1中运行):

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

mysql> select * from users where name="qqq" and locked <>1 limit 1 for update;
+-----+------+--------+
| id  | name | locked |
+-----+------+--------+
| 891 | qqq  |      0 |
+-----+------+--------+
1 row in set (0.00 sec)

mysql>

对查询运行说明:enter image description here

交易2(在终端2中运行):

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

mysql> select * from users where name="xxx" and locked <>1 limit 1 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql>

我正在使用REPEATABLE-READ隔离级别。据我所知,第一个事务中select返回的行将被锁定,直到发出提交为止。 但是,为什么我在第二次交易中的选择被阻止并等待第一笔交易结束,尽管我正在搜索不同的名称?!

1 个答案:

答案 0 :(得分:1)

没有看到桌子的DDL,我无法肯定地说。但是,我的猜测是你的第二个选择是尝试进行全表扫描,以便应用你的where子句。您搜索的列是否包含在索引或主键中?如果没有,那么在运行第二个查询时,MySQL无法知道您在第一个查询中返回的行中的内容。据它所知,它可能是匹配的,应该返回。