【问题标题】:DB2 Read committed without locking?DB2 读取已提交但未锁定?
【发布时间】: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


【解决方案1】:

我假设您说的是 jdbc 隔离级别,而不是 db2。 read_committed(db2 中的游标稳定性)和 repeatable_read(读稳定性)之间的区别在于共享锁的保留时间。 repeatable_read 保留满足谓词的每个锁,而 read_committed 只保留锁,直到找到与谓词匹配的另一行。

您比较过这些计划吗?如果计划不同,您最终可能会有不同的行为。

是否有任何升级发生?

您是否尝试过 CURRENTLY_COMMITTED(假设您使用的是 9.7+)?

precurrent_committed 那里有以下设置,DB2_SKIPINSERTED、DB2_EVALUNCOMMITTED 和 DB2_SKIPDELETED

【讨论】:

  • 不,这种僵局不是基于升级的,尽管我们过去曾遇到过这种情况。我从未听说过 CURRENTLY_COMMITTED。我会去读一读。
  • 我读到了这个,这正是我们想要的。 Cur_commit 是不死锁和不脏读的金发姑娘区。不幸的是,我们使用的是 v9.5,但我们已经在进行转换以推出 v10.5,所以我们只需要等待一小会儿。谢谢。
【解决方案2】:

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

通常,您会像这样处理 DB2 数据库中的行:

  1. 在没有读锁的情况下读取数据库行(普通的 SELECT 已提交读)。
  2. 处理数据,以便您拥有更改值的行。
  3. 再次读取数据库行,使用读取锁。 (选择更新)
  4. 检查以查看 1 中的数据库行。与 3 中的数据库行匹配。
  5. 如果行匹配,更新数据库行。
  6. 如果行不匹配,释放更新锁并返回到 2。

【讨论】:

  • 除此之外,我认为 OP 希望在处理过程中防止对行进行任何更改。这将允许报告,但不会阻止更改。
  • @GilbertLeBlanc 我认为你误解了这个问题。问题是读取提交时的读取操作会锁定记录,尽管是短暂且非排他性的。但是因为它想获得一个锁,如果另一个事务已经锁定了行,读取将等待而不是完成。这通常不是什么大问题,但在我第一段中描述的情况下,这会产生死锁 b/c 服务和客户端在不同的连接上,即使它们一起工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-27
  • 1970-01-01
  • 2015-05-20
  • 1970-01-01
  • 2011-05-12
  • 2010-12-06
  • 2011-09-24
相关资源
最近更新 更多