【发布时间】:2014-07-29 08:07:16
【问题描述】:
我们有一个正在修改记录的事务。事务必须调用 Web 服务,如果服务失败则回滚事务(因此不能事先提交)。由于记录被修改,客户端应用程序对其进行了锁定。但是,作为处理的一部分,Web 服务必须检索该记录以从中获取信息。 Bam,僵局。
我们使用 websphere,出于令我难以置信的原因,它默认为可重复读取隔离级别。我们将其敲低为 read_committed,认为这会在不寻求锁的情况下检索该行。在我们的开发环境中,它似乎可以工作,但在登台时我们遇到了死锁。
我不是在问为什么它的行为不同,我们可能在某个地方犯了错误。我也没有询问上面 Web 服务示例的细节,因为很明显,同样的事情也可能发生在其他地方。
但根据阅读文档,似乎 read_committed 在读取期间确实获得了共享锁,因此将等待另一个事务(在本例中为客户端应用程序)持有的独占锁。但我不想进入 read_uncommitted 隔离级别,因为我不想要脏读。有没有不太极端的解决方案?我需要一些中间地带,我可以在没有任何锁等待的情况下执行读取,并且只检索已提交的数据。
有这样的金发姑娘解决方案吗?不是太死锁,不是太脏读?如果不在隔离级别,也许我可以在我的 SQL 上添加一些修饰符?有什么事吗?
【问题讨论】:
-
锁定的目的是为了防止其他东西改变行,对吧?不是为了以后可以更新吗?或者是否可以允许其他进程更新该行,您的进程只需要事后处理?您可以“本地”调用网络服务吗?我知道 db2 支持为同一个会话共享锁,但是如果您先进行脱机路由,这可能不会发生。其他网络服务的锁定级别是多少?
-
@Clockwork-Muse - 不,客户端确实在锁定以准备更新。 Web 服务实现了一个自定义工作流通知方案,该方案必须查询相关记录以构建通知(尽管它正在读取不同的字段而不是正在更新,但这并没有真正改变任何东西)。 Web 服务和客户端当前在读取提交时运行。我担心最简单的解决方法(由我们的数据库负责人支持)是更改为读取未提交的服务,但我正在尝试找到一个替代的 b/c 我讨厌这个答案。
-
您是否关心其他人是否同时更新了该行?无论发生什么其他操作,这些值是否可以让您在之后用差异更新它们?或者只是不在乎其他人是否同时更新了记录并覆盖了更改?你确定你不能在与服务相同的盒子上运行它,可能让它成为同一个会话的一部分吗?
-
@Clockwork-Muse 相同的盒子,虽然作为一个网络服务,但这并不总是正确的。不同的连接池。我希望 Web 服务不寻求共享锁,并在查询时返回 COMMITTED 数据。我目前的理解是,前者只能发生在未提交的读取中,这会将脏读带入折叠中。 Web 服务是纯只读的。但是因为已提交读寻求共享锁,所以它会等待独占锁被释放……因为客户端拥有它并且正在等待 Web 服务,所以它不会被释放。我不想要未提交的数据,这就是我不喜欢 UR 的原因。
标签: db2 deadlock isolation-level dirtyread