8.3 使用锁

X DevAPI 通过 lockShared()lockExclusive() 方法支持 MySQL 锁定,这些方法适用于 Collection.find() 和 Table.select() 方法。这使您能够控制行锁定以确保对集合的安全、事务性文档更新,并避免并发问题,例如在使用 modify() 方法时。本节介绍如何对 Collection.find() 和 Table.select() 方法使用 lockShared()lockExclusive() 方法。有关锁定的更多背景信息,请参见 锁定读取

无论 lockShared()lockExclusive() 方法与 Collection 还是 Table 一起使用,它们都具有以下属性。

  • 允许对锁定方法进行多次调用。如果在另一个事务持有相同锁定的情况下执行锁定语句,则它将阻塞,直到另一个事务释放锁定。如果对锁定方法进行多次调用,则最后调用的锁定方法优先。换句话说,find().lockShared().lockExclusive() 等效于 find().lockExclusive()

  • lockShared()SELECT ... LOCK IN SHARE MODE 具有相同的语义。对读取的任何行设置共享模式锁定。其他会话可以读取这些行,但不能修改它们,直到您的事务提交。如果这些行中的任何一行被另一个尚未提交的事务更改,则您的查询将等待该事务结束,然后使用最新值。

  • lockExclusive()SELECT ... FOR UPDATE 具有相同的语义。对于搜索遇到的任何索引记录,它会锁定这些行以及任何关联的索引条目,就像您对这些行发出 UPDATE 语句一样。其他事务被阻止更新这些行,执行 SELECT ... LOCK IN SHARE MODE 或在某些事务隔离级别下读取数据。一致性读取会忽略对读取视图中存在的记录设置的任何锁定。无法锁定记录的旧版本;它们是通过将撤销日志应用于记录的内存副本而重建的。

  • 锁定在获取它们的交易存在期间一直保持。它们在语句完成后立即释放,除非交易处于打开状态或自动提交模式已关闭。

两种锁定方法都支持 NOWAITSKIP LOCKED InnoDB 锁定模式。有关更多信息,请参见 使用 NOWAIT 和 SKIP LOCKED 进行锁定读取并发。要将这些锁定模式与锁定方法一起使用,请传入以下之一

  • NOWAIT - 如果函数遇到行锁定,它将中止并生成 ER_LOCK_NOWAIT 错误

  • SKIP_LOCKED - 如果函数遇到行锁定,它将跳过该行并继续

  • DEFAULT - 如果函数遇到行锁定,它将等待,直到没有锁定。等效于在没有模式的情况下调用锁定方法。

锁定注意事项

使用锁定模式时,请注意以下事项

  • autocommit 模式意味着始终存在一个交易,该交易在 SQL 语句执行时会自动提交。

  • 默认情况下,会话处于自动提交模式。

  • 在调用 startTransaction() 时,会隐式禁用自动提交模式。

  • 在自动提交模式下,如果获取了锁定,则在语句完成后会释放该锁定。这可能会导致您得出结论认为没有获取锁定,但实际上并非如此。

  • 同样,如果您尝试获取已被其他人拥有的锁定,则该语句将阻塞,直到其他锁定被释放。