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
,或阻止在某些事务隔离级别下读取数据。一致性读取会忽略对读取视图中存在的记录设置的任何锁定。无法锁定旧版本的记录;它们是通过在记录的内存副本上应用撤消日志来重建的。只要获取锁的事务存在,就会一直持有这些锁。除非打开了事务或关闭了自动提交模式,否则它们会在语句结束后立即释放。
这两种锁定方法都支持 NOWAIT
和 SKIP LOCKED
InnoDB
锁定模式。有关更多信息,请参阅 使用 NOWAIT 和 SKIP LOCKED 锁定读取并发。要将这些锁定模式与锁定方法一起使用,请传入以下之一:
NOWAIT
- 如果函数遇到行锁定,它将中止并生成ER_LOCK_NOWAIT
错误SKIP_LOCKED
- 如果函数遇到行锁定,它将跳过该行并继续DEFAULT
- 如果函数遇到行锁定,它将等待,直到没有锁定为止。相当于在不使用模式的情况下调用锁定方法。
使用锁定模式时,请注意以下事项:
autocommit
模式意味着始终有一个事务处于打开状态,该事务在执行 SQL 语句时自动提交。默认情况下,会话处于自动提交模式。
当您调用
startTransaction()
时,会隐式禁用自动提交模式。在自动提交模式下,如果获取了锁,则在语句结束后释放该锁。这可能会导致您得出结论,认为没有获取锁,但事实并非如此。
同样,如果您尝试获取其他人已拥有的锁,则该语句会阻塞,直到释放另一个锁。