2016-11-13 2 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; 

を持っていると私は私が最後の更新(同じテーブルから1行)を作る人と言う行を更新しようとしている次のエラー

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

トリガーはテーブルMESSAGESに基づいています。このテーブルの更新が完了すると、トリガーが起動します。しかし、トリガーは同じテーブルで更新を実行したいが、テーブルは最初の更新によってまだロックされています。 – wieseman

+0

MESSAGEテーブルのafter文トリガを使用する必要があると思います。使用前の更新トリガでは、plsql表を埋める必要があり、after文トリガでは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; 
/

また、電子メールを探すクエリのロジックが複雑すぎます。確かにあなたはそれを単純化することができます。

関連する問題