我有一个关于/OS的游标中的FOR DB2子句的问题。假设隔离级别游标稳定(绑定命令中的标准参数)。DB2版本是11。
我的第一个问题是:使用FOR UPDATE子句编码的游标能否阻止并发事务读取游标当前所在的行?我的第二个问题是:更新.那里的电流..。语句检测已更新的行在游标打开后和从游标结果集获取之前更改了什么时候?
关于这些问题,我在网上读到了一些自相矛盾的陈述。根据我(当前)的理解,FETCH操作只需要获取行上的更新锁,因此并发事务至少可以读取同一行。CURSOR只有在游标的电流实际完成的情况下才被提升为X(取决于应用程序逻辑)。但这让我感到困惑,因为这样做不会防止丢失更新现象(当并发进程在完成第一个进程的更新之前读取该值时,它将继续使用旧值处理该值,并覆盖通过游标当前更新的第一个进程的更新)。
发布于 2021-10-03 02:02:24
使用
FOR UPDATE子句编码的游标能否阻止并发事务读取当前游标所在的行?
否-使用隔离级别CS,Db2将在当前行上持有一个U锁,该锁与可能需要的S锁兼容(请参阅稍后关于当前数据绑定参数的注释及其对读者避免S锁的影响)。
UPDATE ... WHERE CURRENT OF语句是否检测在游标打开后和从游标结果集中获取之前已更新的行何时发生更改?
否-使用隔离级别CS,Db2在读取行之前不会获得锁。如果要求数据在OPEN CURSOR之后保持不变,则需要不同的隔离级别。
但这让我感到困惑,因为这样做不会防止丢失更新现象(当并发进程在完成第一个进程的更新之前读取该值时,它将继续使用旧值处理该值,并覆盖通过游标当前更新的第一个进程的更新)。
假设这两个事务都在使用FOR UPDATE和UPDATE ... WHERE CURRENT OF,那么这种情况就不会发生。每次读取都会尝试获取一个U锁。由于U锁彼此不兼容,第二读将等待第一个U锁被释放。(https://www.ibm.com/docs/en/db2-for-zos/12?topic=locks-lock-modes-compatibility)
对于一个(或两个)事务不使用FOR UPDATE和UPDATE ... WHERE CURRENT OF的更复杂的情况,可能会出现丢失的更新现象。
很久以前,Db2引入了绑定参数CURRENTDATA来帮助控制这种行为。
Gareth在这方面有一些很棒的文章,还有更多的细节- 面向应用程序开发人员的Db2 for z/OS锁定第8部分。
要完全防范更新丢失的风险,一种很好的方法是添加谓词,以确保更新只针对预期的数据进行。Gareth在他关于锁定的博客的第九编中提供了三个选项。一般的想法是有类似更新时间戳的东西,当行的任何部分被更新时,更新时间戳总是被更新的。然后在WHERE语句的UPDATE子句中包含一个谓词,以确保只有当更新时间戳与最初读取行时相同时才会发生更新。ROW CHANGE TIMESTAMP 9中的Db2特性使这种方法更容易实现。
https://stackoverflow.com/questions/69405599
复制相似问题