DB2无锁读取提交事务?

3
我们有一个正在修改记录的事务。该事务必须调用Web服务,如果服务失败,则回滚该事务(因此不能在提交之前提交)。由于记录已经被修改,客户端应用程序对其进行了锁定。但是,Web服务必须检索该记录以获取其中的信息作为其处理的一部分。嘭,死锁。
我们使用WebSphere,默认情况下使用可重复读取隔离级别,原因令人费解。我们将其降低到read_committed,认为这将检索到行而不寻求锁定。在我们的开发环境中,似乎可以工作,但在暂存期间,我们遇到了死锁问题。
我不是在问它为什么表现不同,我们可能犯了错误。我也没有询问上面Web服务示例的具体细节,因为显然这种情况可能会发生在其他地方。
但是根据阅读文档,read_committed在读取期间确实会获取共享锁,并因此等待另一个事务(在本例中为客户端应用程序)持有的排他锁。但是,我不想进入read_uncommitted隔离级别,因为我不想要脏读。有没有一个稍微缓和的解决方案?我需要一些中间状态,可以执行读取而不等待任何锁定,并仅检索已提交的数据。
有没有这样的解决方案?不太容易死锁,也不太容易脏读?如果在隔离级别中没有,则可以对SQL添加一些修饰符吗?还有其他的吗?

锁的要点是为了防止其他东西更改行,对吗?不是为了稍后更新它?或者允许其他进程更新该行,但您的进程必须在此之后处理它是否可能?您可以“本地”调用webservice吗?我知道db2支持为同一会话共享锁,但如果您首先将其路由到箱外,则可能不会发生。其他webservice的锁定级别是什么? - Clockwork-Muse
@Clockwork-Muse - 不,客户端确实是在更新准备中锁定的。 Web服务实现了一个自定义工作流通知方案,必须查询相关记录以构建通知(尽管它正在读取不同于正在更新的字段,但这并没有真正改变任何内容)。 Web服务和客户端目前运行在读提交模式下。 我担心最简单的修复方法(由我们的DB负责人支持)是将服务更改为读未提交,但我正在尝试找到另一种选择,因为我讨厌那个答案。 - Entropy
你是否在意其他人同时更新该行?这些值是否可以通过差异后进行更新,而不管发生了什么其他操作?或者只是不在意其他人在此期间更新记录,并覆盖更改?您确定无法在同一台计算机上运行此服务,可能使其成为同一会话的一部分吗? - Clockwork-Muse
@Clockwork-Muse 同一个盒子,但作为 Web 服务,这并不总是正确的。不同的连接池。我希望 Web 服务不要寻求共享锁,并在查询时返回 COMMITTED 数据。我目前的理解是前者只能发生在未提交读取中,这会引入脏读。Web 服务是纯读取模式。但是,由于读取已提交会寻求共享锁,因此它会等待独占锁被释放...但客户端持有该锁并正在等待 Web 服务,因此它将永远不会被释放。我不想要未提交的数据,这就是为什么我不喜欢 UR 的原因。 - Entropy
2个回答

1
我假设你在谈论jdbc隔离级别,而不是db2。read_committed(db2中的游标稳定性)和repeatable_read(读取稳定性)之间的区别在于共享锁的保留时间。repeatable_read会保留满足谓词的每个锁定,另一方面,read_committed只保留锁定,直到找到与谓词匹配的另一行。
你比较过计划了吗?如果计划不同,您可能会得到不同的结果。
是否有任何升级发生?
你尝试过CURRENTLY_COMMITTED吗(假设您使用的是9.7+)?
在当前提交之前,还有以下设置:DB2_SKIPINSERTED、DB2_EVALUNCOMMITTED和DB2_SKIPDELETED。

不,这个死锁不是升级型的,虽然我们过去有过这样的情况。我从未听说过CURRENTLY_COMMITTED。我会去了解一下。 - Entropy
我已经研究了这个问题,它正是我们想要的。Cur_commit是既不会死锁也不会脏读的黄金区域。不幸的是,我们使用的是v9.5版本,但我们已经在进行转换工作以升级到v10.5,所以我们只需要等待一段时间即可。谢谢。 - Entropy

0

读取提交的行的最低隔离级别是读提交。

通常,您在 DB2 数据库中以以下方式处理行:

  1. 使用无读锁的方式读取数据库行(使用读提交的普通 SELECT)。
  2. 处理数据,使其具有更改后的值的行。
  3. 再次读取带有读取锁的数据库行。(SELECT for UPDATE)
  4. 检查第1步中的数据库行是否与第3步中的数据库行匹配。
  5. 如果行匹配,请更新数据库行。
  6. 如果行不匹配,则释放更新锁并返回第2步。

除此之外,我认为 OP 希望在处理过程中防止对行进行任何更改。这将允许报告,但不会阻止更改。 - Clockwork-Muse
@GilbertLeBlanc 我认为你稍微误解了问题。问题在于,在读取提交时,读操作确实会锁定记录,尽管是短暂且非排他性的。但是因为它想要获取锁,如果不同的事务已经锁定了该行,则读取将等待而不是完成。通常这并不是什么大问题,但在像我第一段所描述的场景中,这会生成死锁,因为服务和客户端在不同的连接上,即使它们正在协同工作。 - Entropy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接