mysql for update语法实现行锁

DB2数据库中可以在select语句最后使用with ur来为查询的记录加锁,而mysql没有这种语法,某
些情况下,我们可以在select语句最后加FOR UPDATE来对所查询的行加锁

for update 为select 语句加写锁

默认情况下,select语句是不会对数据加写锁的,也就是不会阻止写入(update delete)

通过使用 for update可以对数据加写锁

必须在begin/commit或者autocommit=0的情况下

下面使用test表中,id字段是自增型主键

##行锁
如果是按照主键查询的话,那么加的是行锁

  1. 在第一个连接中

    1
    2
    begin;
    select * from test where id =10015 for update;
  2. 在第二个连接中执行:

    1
    update test set name='abc' where id=10015 ;

可以看到第二个连接的update语句一直在等待。

  1. 在第三个连接中执行
    1
    update test set name='fgh' where id=10016 ;

Query OK, 1 row affected (0.00 sec)可以看到瞬间执行结束。
说明按主键查询的话,加的是行锁

  1. 在第一个连接中commit
    1
    commit;

第一个连接commit之后,这时可以看到,第二个连接中的update语句执行成功。

表锁

如果查询条件不是按主键查询那么会对整个表加表锁

  1. 在第一个连接中执行

    1
    2
    begin;
    select * from test where name='abc' for update;
  2. 在第二个连接中执行

    1
    update test set name='fgh' where id=10016 ;

可以看到,虽然 连接1中where name='abc'的条件只能匹配id=10015的一行,但是锁定了整张表

  1. 在第一个连接中commit
    1
    commit;

第一个连接commit之后,这时可以看到,第二个连接中的update语句执行成功。

某些条件下依然可以行锁

1
mysql$ select * from test where id = (select * from test where name='abc') for update;

where id = ()仍然是行锁,如果你换成 where id IN () 那么是 表锁