2016-11-13 10 views
0

У меня есть следующий триггерPL/SQL Почему я получаю DEADLOCK на действие триггера?

CREATE OR REPLACE TRIGGER LAST_EDIT 
    BEFORE UPDATE ON MESSAGES 
    FOR EACH ROW 
    DECLARE 
    pragma autonomous_transaction; 
    BEGIN 
    if :NEW.TEXT <> :OLD.TEXT THEN 
     UPDATE MESSAGES set MESSAGES.LAST_EDITED=(select USERS.EMAIL from USERS inner join LAST_EDITED_TABLE on users.ID=LAST_EDITED_TABLE.USER_ID where 
     LAST_EDITED_TABLE.MESSAGE_ID=(select MESSAGE_ID from LAST_EDITED_TABLE where DATE_MESSAGE=(select max(DATE_MESSAGE) from LAST_EDITED_TABLE))); 
    ENDIF; 
COMMIT; 
END; 

И я получаю следующую ошибку

ORA-06512: at "DIP.MESSAGEPACKAGE", line 35 
00060. 00000 - "deadlock detected while waiting for resource" 
*Cause: Transactions deadlocked one another while waiting for resources. 
*Action: Look at the trace file to see the transactions and resources 
      involved. Retry if necessary 

Я пытаюсь обновить строку, которая говорит, кто делает последнее обновление (одна строка из одной таблицы). Кто-нибудь может мне помочь, пожалуйста!

+0

Триггер основан на таблицах СООБЩЕНИЯ. Если обновление в этой таблице выполняется, срабатывает триггер. Но триггер хочет сделать обновление в той же таблице, но таблица по-прежнему заблокирована первым обновлением. – wieseman

+0

Я думаю, что вы должны использовать триггер после оператора в таблице MESSAGE. В используемом триггере обновления вы должны заполнить таблицу plsql, а в триггере после инструкции вы должны прочитать записи таблицы plsql, а затем выполнить то, что вы должны сделать. В этом случае это будет бесконечный цикл. ==> обновление будет иметь дело с другим обновлением, будет иметь другое обновление .... – wieseman

+0

Ваш дизайн потенциально слишком сложный. Почему бы просто не потребовать, чтобы обновитель также обновил правильное значение до 'messages.last_edited_by_user'? – user272735

ответ

1

Разве вам это не нужно?

CREATE OR REPLACE TRIGGER LAST_EDIT 
BEFORE UPDATE ON MESSAGES 
FOR EACH ROW 
DECLARE 
    email USERS.EMAIL%type; 
BEGIN  
if :NEW.TEXT <> :OLD.TEXT THEN 
    select USERS.EMAIL into email 
    from USERS inner join LAST_EDITED_TABLE on users.ID=LAST_EDITED_TABLE.USER_ID 
    where LAST_EDITED_TABLE.MESSAGE_ID = (select MESSAGE_ID from LAST_EDITED_TABLE where DATE_MESSAGE = (select max(DATE_MESSAGE) from LAST_EDITED_TABLE)); 
    :NEW.LAST_EDITED = email; 
END IF; 
COMMIT; 
END; 
/

Также логика в запросе, который ищет электронную почту, слишком сложна. Конечно, вы можете это упростить.

 Смежные вопросы

  • Нет связанных вопросов^_^