Warum muss ich mich beim Datenbank-Trigger nicht verpflichten?

7

Wir können COMMIT / ROLLBACK in DML-Triggern nicht ausführen, da die Transaktion nach der DML-Anweisung manuell behandelt wird. Datenbank-Trigger scheinen jedoch eine Ausnahme zu sein. Angenommen, es gibt einen Datenbank-Trigger:

CREATE OR REPLACE TRIGGER user_login_as
  AFTER LOGON 
    ON SCHEMA
BEGIN
  INSERT INTO user_login_log(username, log_date, action) VALUES (user, sysdate, 'User has logged in');
END user_login_as;

Der Trigger enthält keine autonome Transaktionsprozedur mit darin enthaltenem Commit. Wer schreibt also die Einfügung fest? Dieser Trigger funktioniert wie ein Zauber und fügt nach der Benutzeranmeldung einen neuen Datensatz in die Protokolltabelle ein. Es riecht nach versteckter Oracle-Funktionalität und ich kann in Oracle-Dokumenten keine Referenz dazu finden. Ich benutze Oracle11g.

Zenturio
quelle
Sorry @NickChammas, um Ihre Antwort intakt zu halten, hat zu schnell geklickt.
Aaron Bertrand

Antworten:

13

Sie erhalten automatisch einen autonomen Transaktionskontext für diese Trigger.

Aus den CREATE TRIGGERDokumenten:

Ein oder mehrere bestimmte Zustände der Datenbank, die den Auslöser auslösen können. Sie können Trigger für diese Ereignisse in DATABASE oder SCHEMA erstellen, sofern nicht anders angegeben. Für jedes dieser auslösenden Ereignisse öffnet die Datenbank einen autonomen Transaktionsbereich , löst den Trigger aus und schreibt eine separate Transaktion fest (unabhängig von einer vorhandenen Benutzertransaktion).

Was passiert, wenn der Trigger ausfällt, hängt vom genauen Trigger / Ereignis ab. Siehe Ausnahmebehandlung in Triggern . Insbesondere ein Anmeldetrigger, der mit einer Ausnahme fehlschlägt, kann Nicht-DBA-Benutzer sehr gut sperren. Die Ausnahme führt dazu, dass die Anmeldung fehlschlägt, es sei denn, der Benutzer verfügt über bestimmte Berechtigungen.

Matte
quelle
Es ist interessant, was passiert, wenn im Trigger-Body eine Ausnahme auftritt. Ich gehe davon aus, dass Oracle in diesem Fall einen "stillen" Rollback durchführt.
Centurion
Mit etwas mehr Informationen dazu bearbeitet.
Mat
-1
CREATE OR REPLACE TRIGGER t_trigger
AFTER INSERT ON t1 FOR EACH ROW

DECLARE
  PRAGMA AUTONOMOUS_TRANSACTION;
 i PLS_INTEGER; 
BEGIN
  SELECT COUNT(*)
  INTO i
  FROM t1;

  INSERT INTO t2
  VALUES
  (i);
  COMMIT;
END;
/
user101557
quelle
3
Könnten Sie bitte erklären, was uns das sagt?
Dekso
-1

Ein Commit innerhalb eines Triggers würde die grundlegende Definition einer atomaren Transaktion zunichte machen (siehe ACID). Die Triggerlogik ist per Definition eine Erweiterung der ursprünglichen DML-Operation. Innerhalb von Triggern vorgenommene Änderungen sollten daher im Rahmen der Transaktion, in der sie ausgeführt werden, festgeschrieben oder zurückgesetzt werden. Aus diesem Grund dürfen Trigger KEINE COMMIT- oder ROLLBACK-Anweisungen ausführen (mit Ausnahme autonomer Trigger). Hier ist ein Beispiel dafür, was passieren wird, wenn sie es tun:

SQL> CREATE TABLE tab1 (col1 NUMBER);
Table created.

SQL> CREATE TABLE log (timestamp DATE, operation VARCHAR2(2000));
Table created.

SQL> CREATE TRIGGER tab1_trig
  2     AFTER insert ON tab1
  3  BEGIN
  4     INSERT INTO log VALUES (SYSDATE, 'Insert on TAB1');
  5     COMMIT;
  6  END;
  7  /
Trigger created.

SQL> INSERT INTO tab1 VALUES (1);
INSERT INTO tab1 VALUES (1)
            *
ERROR at line 1:
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "SCOTT.TAB1_TRIG", line 3
ORA-04088: error during execution of trigger 'SCOTT.TAB1_TRIG'

Autonome Transaktionen:

Als Problemumgehung können autonome Transaktionen verwendet werden. Autonome Transaktionen werden getrennt von der aktuellen Transaktion ausgeführt.

Im Gegensatz zu regulären Triggern können autonome Trigger COMMIT- und ROLLBACK-Anweisungen enthalten. Beispiel:

SQL> CREATE OR REPLACE TRIGGER tab1_trig
  2    AFTER insert ON tab1
  3  DECLARE
  4    PRAGMA AUTONOMOUS_TRANSACTION;
  5  BEGIN
  6    INSERT INTO log VALUES (SYSDATE, 'Insert on TAB1');
  7    COMMIT; -- only allowed in autonomous triggers
  8  END;
  9  /
Trigger created.

SQL> INSERT INTO tab1 VALUES (1);
1 row created.

Beachten Sie, dass im obigen Beispiel Protokolleinträge eingefügt und festgeschrieben werden - auch wenn die Haupttransaktion zurückgesetzt wird!

Denken Sie daran, dass eine Prozedur / Funktion / Auslöser für "autonome_Transaktion" eine ganze Transaktion für sich ist und daher mit einem Commit oder einer Rollback-Anweisung enden muss.

vishal
quelle
1
Dies beantwortet die Frage nicht wirklich - das OP hat klar verstanden, warum es in DML-Triggern keine Transaktionslogik benötigte. Die Frage betraf Datenbank-Trigger, um die sich die veröffentlichte und akzeptierte Antwort kümmerte.
RDFozz