【问题标题】:deadlock detected while waiting for resource等待资源时检测到死锁
【发布时间】:2013-09-04 04:35:36
【问题描述】:

我一直在努力让这个查询启动并运行,但一直遇到死胡同,我已经阅读了很多论坛,但我找不到我的问题的解决方案。 我最初的错误是表突变错误,我知道 oracle 仍在忙于处理表,因此无法执行我的第二个任务。基本上我有一个名为 project_tbl 的表和另一个表,它是该表的副本,名为 proj_archive_tbl。我的逻辑是,当 project_tbl 中名为 proj_status 的列更改为已完成时,它必须将整行插入 proj_archive_tbl,然后将 project_tbl 中的 deleted_status 列更改为'X'。

我的第一次尝试是执行并插入 proj_archive_tbl 的触发器,然后更新 project_tbl delete_status = 'X' 但我得到了突变错误。

现在我创建了 2 个触发器,一个用于在项目表上的状态更改为完成时将数据复制到存档表,另一个触发器在将新行插入 proj_archive_tbl 时,将项目 delete_status 更新为“X”但得到“死锁”在等待资源时检测到”。我曾尝试使用数组创建一个包,但我很挣扎,因为我是 oracle 的新手,并且还尝试遵循 asktom 建议、复合触发器和 antonomous_transactions,但都无济于事。这是代码,如果有人可以帮助我或以正确的方式指导我,将不胜感激:

create or replace 
trigger Arch_Proj_trigger
    after update of proj_status on project_tbl
    for each row
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
begin
if upper(:new.proj_status) = UPPER('completed') then
    insert into proj_archive_tbl 
        values (
          :old.proj_code,
          :old.proj_name,
          :old.cust_code,
          :old.proj_manager,
          :old.start_date,
          :old.end_date,
          :old.max_budget,
          :new.proj_status,
          :old.delete_status);
end if;
commit;

结束;

create or replace 
trigger Mark_Proj_Deleted
after insert on proj_archive_tbl
for each row
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
begin
    update project_tbl set delete_status = 'X' 
    where proj_code = :new.proj_code;
commit;

结束;

我希望我使用的是正确的论坛并且提供了足够的信息。 请帮忙! 阿德里安

【问题讨论】:

    标签: sql oracle plsql plsqldeveloper


    【解决方案1】:

    这种方法行不通。以下是导致死锁的原因:

    1. 当您更新project_tbl 中的行时,您的事务将获得行锁并应用更改
    2. 您的触发器arch_proj_trigger 在更新后触发,并在表proj_archive_tbl 中插入一行
    3. 插入proj_archive_tbl 表会导致触发器mark_proj_deleted 触发 - 这无法更新project_tbl 中的行,因为在您更新状态时原始事务仍保持其行锁定
    4. 在第二个触发器完成之前,第一个触发器无法完成 - 但第二个触发器永远不会完成,因为原始更新语句正在阻止它。

    我通常不提倡在触发器中使用这种应用程序逻辑 - 出于上述原因和其他原因。一般来说,如果您开始遇到死锁或突变问题,则该方法是错误的。

    我的建议是使用 PL/SQL 过程来执行这种类型的数据操作,并且不允许对表进行直接更新语句。至少通过这种方式,您实现了所需的控制,并且一切都变得更加简单并且(更重要的是)在事务上是合理的。

    【讨论】:

    • 感谢您的快速回复。这是针对学术任务的,要求我们需要创建 5 个触发器。我认为这将是一个很好的触发器,但遇到了太多麻烦。将丢弃并使用程序:)
    • 如果你想增加触发器计数,理论上你仍然可以使用触发器将更新的行复制到 proj_archive_tbl 表中。
    猜你喜欢
    • 2011-03-05
    • 2021-04-20
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    • 2016-01-22
    • 2016-09-02
    • 1970-01-01
    • 2013-12-13
    相关资源
    最近更新 更多