我有两个要在同一张表上运行的程序,一个使用出生日期,另一个更新取自第三张表的姓名和姓氏。
使用生日来更新年龄字段的那个在整个表中运行,而更新名字和姓氏的那个只根据一个键更新出现在第三个表上的行。
所以我同时启动并陷入僵局!有没有办法优先考虑它们中的任何一个?我阅读了有关nowait
更新的和跳过锁定的信息,但是,我将如何返回已跳过的内容?
希望你能在这方面帮助我!!
我猜你被锁定是因为所有行的更新和一小组行的更新以不同的顺序访问行。
前者使用完整扫描并首先到达原始 A,然后继续到其他行,最终尝试锁定 B 行。但是,另一个查询是从索引或连接驱动的,并且已经锁定了 B 行,并且正在关闭当发现 A 行已被锁定时,将其锁定。
所以,解决方法:首先,拥有一个需要不断修改的年龄列是一个非常糟糕的主意。也许这样做是为了允许对年龄进行索引,但是通过正确编写的查询,出生日期的索引可以让您同样快速地找到相同的记录。您已经破坏了规范化规则并最终为自己编写了一个死锁应用程序。希望您只更新需要更新的行,而不是全部更新——我的意思是,这太疯狂了。
最好的解决方案是摆脱这个设计缺陷。
不太好的解决方案是通过在不同时间运行查询或使用 DBMS_Lock 来消除查询冲突,以便在任何时候都只能运行其中一个。
一种可能性是锁定您将立即更新的所有行。在单个更新语句中执行所有更新将完成此操作。或者
从 T 中选择任何内容 在哪里 ... 用于更新;
另一个解决方案是创建我称之为“Gatekeeper”的表。这两个过程都需要在更新相关表之前将 Gatekeeper 表锁定为独占模式。第二个过程将阻塞直到第一次提交,但不会死锁。在 11g 中,您可以创建一个没有分配空间的表。
一种变体是在 Gatekeeper 中插入一行。然后使用 select for update 仅锁定该行。然后您可以在其他情况下使用 Gatekeeper。