如果某行记录被事务锁住了,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对于基于语句的复制是不安全的。
# Session 1: mysql> CREATE TABLE t (i INT, PRIMARY KEY (i)) ENGINE = InnoDB; mysql> INSERT INTO t (i) VALUES(1),(2),(3); mysql> START TRANSACTION; mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE; +---+ | i | +---+ | 2 | +---+ # Session 2: mysql> START TRANSACTION; mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE NOWAIT; ERROR 3572 (HY000): Do not wait for lock. # Session 3: mysql> START TRANSACTION; mysql> SELECT * FROM t FOR UPDATE SKIP LOCKED; +---+ | i | +---+ | 1 | | 3 | +---+