如果某行记录被事务锁住了,select ... for update、或select ... for share事务对相同的行加锁的时候必须等待,直到产生阻塞的事务释放锁。
为了避免等待事务释放锁定的行,nowait和skip locked选项可以被用于select ... for update或select ... for share语句:
·nowait:使用了nowait选项的锁定读操作,会立即执行,如果读的记录被锁定了就会报错
·skip locked:使用了skip locked选项的锁定读操作,会立即执行,如果读的记录被锁定了就会从结果集移除该记录。返回的数据是非一致性的。因此,不适用于常规的事务。
nowait和skip locked只适用于行级锁。
nowait和skip locked对于基于语句的复制是不安全的。
1# Session 1: 2 3mysql> CREATE TABLE t (i INT, PRIMARY KEY (i)) ENGINE = InnoDB; 4 5mysql> INSERT INTO t (i) VALUES(1),(2),(3); 6 7mysql> START TRANSACTION; 8 9mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE; 10+---+ 11| i | 12+---+ 13| 2 | 14+---+ 15 16# Session 2: 17 18mysql> START TRANSACTION; 19 20mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE NOWAIT; 21ERROR 3572 (HY000): Do not wait for lock. 22 23# Session 3: 24 25mysql> START TRANSACTION; 26 27mysql> SELECT * FROM t FOR UPDATE SKIP LOCKED; 28+---+ 29| i | 30+---+ 31| 1 | 32| 3 | 33+---+