【问题标题】:Oracle, 2 procedures avoid deadlockOracle,2个程序避免死锁
【发布时间】:2013-03-26 19:38:01
【问题描述】:

我想在同一张表上运行两个程序,一个使用出生日期,另一个更新取自第三张表的姓名和姓氏。

使用生日来更新年龄字段的那个会在整个表中运行,而更新名字和姓氏的那个只会根据键更新第三个表中出现的行。

所以我同时启动了两者并陷入僵局!有没有办法优先考虑它们中的任何一个?我阅读了nowait 并跳过锁定以进行更新,但是,我将如何返回跳过的内容?

希望你能帮我解决这个问题!

【问题讨论】:

  • 你说的是死锁还是锁争用?优先排序无助于解决死锁
  • 一些事情,1) 请阅读这个链接 - stackoverflow.com/questions/how-to-ask 。 2)请编辑您的问题以显示相关表的模式,以及您所指的相关(或全部)过程代码。我们不是读心术的人。如果您有两个不同的事务以不同的顺序对表进行更新,则通常会发生死锁。如果你有死锁,oracle 应该有一个跟踪显示导致死锁的原因。
  • 为什么不在需要时即时计算年龄?这将消除对第一个 proc 的需求,并且年龄将始终是最新的。
  • 对不起,伙计们,我从来没有问过这样的问题,我的一位同事使用了我的帐户,因为我没有打开我的会话,他遇到了问题,非常感谢你的回答,我会更新这个问题一旦我与他谈论解决方案,就会得到答案!
  • 我认为这是一个很好的问题,也是我提出的第一个问题。它不是特定于模式的,这种类型的事情在很多情况下都会发生。而且它不是特定于数据库的。

标签: oracle deadlock procedure


【解决方案1】:

一种可能性是锁定您将立即更新的所有行。在单个更新语句中执行所有更新将完成此操作。或者

从 T 中选择任何内容
   在哪里 ...
   用于更新;

另一个解决方案是创建我称之为“Gatekeeper”的表。这两个过程都需要在更新相关表之前将 Gatekeeper 表锁定为独占模式。第二个过程将阻塞直到第一次提交,但不会死锁。在 11g 中,您可以创建一个没有分配空间的表。

一种变体是在 Gatekeeper 中插入一行。然后使用 select for update 仅锁定该行。然后你可以在其他情况下使用 Gatekeeper。

【讨论】:

  • 我同意使用某种锁来消除查询冲突,但我讨厌看门人表或行的方法。 DBMS_Lock 可以高效灵活地完成此类任务。
【解决方案2】:

我猜你被锁定是因为所有行的更新和一小部分行的更新以不同的顺序访问行。

前者使用全扫描并首先到达原始 A,然后继续到其他行,最终尝试锁定 B 行。但是,另一个查询是从索引或连接驱动的,并且已经锁定了 B 行,并且当它发现 A 行已经被锁定时,它正在关闭它来锁定它。

因此,解决方法:首先,拥有一个需要不断修改的年龄列是一个非常糟糕的主意。也许这样做是为了允许对年龄进行索引,但是通过正确编写的查询,出生日期的索引可以让您同样快速地找到相同的记录。您违反了规范化规则,最终为自己编写了一个死锁应用程序。希望您只更新需要更新的行,而不是全部更新——我的意思是,这太疯狂了。

最好的解决方案是摆脱这个设计缺陷。

不太好的解决方案是通过在不同时间运行查询或使用 DBMS_Lock 来消除查询冲突,以便在任何时候都只能运行其中一个。

【讨论】:

  • 我更喜欢您的解决方案。唯一的缺点是默认不安装 DBMS_LOCK。
  • 它已安装,但必须授予访问权限。只是特权问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-17
  • 1970-01-01
  • 1970-01-01
  • 2020-10-25
  • 2012-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多