等待资源时检测到死锁

时间:2013-08-31 16:00:05

标签: sql oracle plsql plsqldeveloper

我一直在努力让这个查询启动并运行,但继续遇到死胡同,我已阅读了不少论坛,但我无法找到解决方案。 我最初的错误是表突变错误,我知道oracle仍然忙于表,因此无法执行我的第二个任务。基本上我有一个名为project_tbl的表和另一个表,它是该表的副本,名为proj_archive_tbl。我的逻辑是,当project_tbl中名为proj_status的列更改为completed时,它必须将整行插入proj_archive_tbl,然后将project_tbl中的columns_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;

结束;

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

1 个答案:

答案 0 :(得分:2)

这种方法不起作用。以下是造成僵局的原因:

  1. 当您更新project_tbl中的行时,您的交易将获得行锁并应用更改
  2. 您的触发器arch_proj_trigger随后会在更新后触发,并在表proj_archive_tbl中插入一行
  3. 插入proj_archive_tbl表会导致触发器mark_proj_deleted触发 - 这无法更新project_tbl中的行,因为原始事务仍然保持其更新时的行锁定状态
  4. 第一个触发器在第二个触发器完成之前无法完成 - 但第二个触发器永远不会完成,因为原始更新语句阻止了它。
  5. 我一般不支持在触发器中使用这种应用程序逻辑 - 出于上述原因和其他原因。一般来说,如果你开始遇到死锁或突变问题,那么这种方法是错误的。

    我的建议是使用PL / SQL过程来执行此类数据操作,并禁止针对表的直接更新语句。至少就是这样,你实现了你需要的控件,一切都简单得多,而且(更重要的是)交易声音。