如何在没有超时的情况下锁定 Ibm Db2 中的更新行?

Posted

技术标签:

【中文标题】如何在没有超时的情况下锁定 Ibm Db2 中的更新行?【英文标题】:How to lock row for update in Ibm Db2 without timeouts? 【发布时间】:2018-10-23 18:25:34 【问题描述】:

我需要在 zos 上的 ibm db2 中为每个连接更新一行,而不会出现数据异常。

我选择 FOR UPDATE WITH RS USE AND KEEP 语句,但是有问题。如果一个客户端在数据更新期间持有锁,同时第二个用户尝试读取同一行 - 第二个用户将等待直到锁被释放。

我需要下一个行为:如果行被锁定,第二个用户会收到错误。

在 DB2 11 中是否可行?

【问题讨论】:

您的问题是特定于 Db2 服务器平台的(即用于 Z/OS 的大型机 Db2)。当 Db2 服务器在 Linux/Unix/Windows 上运行时,应用程序可以使用特殊寄存器设置 set current lock timeout NOT WAIT 告诉 Db2 如果 Db2 无法立即获得锁,则立即返回错误。此功能目前不适用于 Db2 for Z/OS,但存在其他方法。 【参考方案1】:

如果我正确阅读了您的请求,如果您可以获得 UPDATE 锁,您要求的是条件 SELECT。我不相信有办法做到这一点。但是,您可以执行以下操作:

SELECT myCount FROM myTable WHERE ID = someValue

然后您可以更新该值并使用 WHERE 子句执行 UPDATE,该子句查找 ID 和 myCount 的原始值。像

这样的序列
SELECT myCount FROM myTable WHERE ID = someValue
origCount = myCount++
UPDATE myTable WHERE ID = someValue AND myCount = origValue

如果您的 UPDATE 显示已更新零行,则表明其他人对其进行了更新,然后您重复该序列或继续您的替代逻辑。

我相信这将实现您正在寻找的内容,而无需检测锁的存在,因为您表示一次访问一行您可以使用 CS 隔离。

这个一般称为Optimistic Concurrency

乐观并发控制(OCC)是一种并发控制方法 应用于关系数据库等事务系统 管理系统和软件事务内存。 OCC 假设 多个事务可以频繁完成而不会干扰 彼此。在运行时,事务使用数据资源而不 获取对这些资源的锁定。在提交之前,每个 事务验证没有其他事务修改数据 它已阅读。如果检查显示有冲突的修改,则 提交事务回滚并且可以重新启动。[1]乐观的 并发控制最早是由 H.T.孔和约翰 T。 罗宾逊

【讨论】:

据了解,只有其他方法可以这样做。例如,您无法可靠地阻止其他应用程序读取被一个应用程序锁定的行。以未提交的读取隔离级别运行的查询甚至能够访问独占锁定的行。使用当前提交的语义以游标稳定性隔离级别运行的查询将访问先前版本的独占锁定行。最佳选择是在状态列中使用特殊值(如“处理”)以防止其他会话处理同一行。 您可以通过锁定来阻止它们,但这听起来像是您试图避免的问题。这是 Db2 锁定语义的参考。 ibm.com/support/knowledgecenter/en/SSEPEK_11.0.0/perf/src/tpc/….【参考方案2】:

更新一条记录的时间很长,最好只读取包含时间戳的记录,然后处理其他记录。当准备好更新时,读取更新,如果时间戳没有改变,则更新记录。如果时间戳已更改,则显示错误。

【讨论】:

以上是关于如何在没有超时的情况下锁定 Ibm Db2 中的更新行?的主要内容,如果未能解决你的问题,请参考以下文章

DB2 操作超时或死锁

IBM DB2 V9 License 安装

如何通过SQL从IBM db2中的查询中获取列名

如何使用 SQL 在 IBM DB2 Z/OS 中的表上显示当前权限

事务运行时间超过锁定超时

C# - 在没有许可证的情况下连接到 DB2 z/os 大型机