8.3 使用锁

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

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

  • 允许多次调用锁定方法。如果锁定语句在其他事务持有相同锁定的情况下执行,它将阻塞,直到其他事务释放它。如果对锁定方法进行多次调用,则最后调用的锁定方法优先。换句话说,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() 时,您会隐式地禁用自动提交模式。

  • 在自动提交模式下,如果获取了锁,它将在语句完成后释放。这可能会让您得出没有获取锁定的结论,但事实并非如此。

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