loggingtriggersfirebirdcdcorder-of-execution

Triggers execution order inside transaction for change tracking


I have a Firebird table Orders with bunch of columns. I have after update triggers that log table information in events_history table in the following manner:

SET TERM ^ ;
CREATE OR ALTER TRIGGER ORG_STRUCTURE_EVNT_HST_AI FOR ORG_STRUCTURE
ACTIVE AFTER INSERT POSITION 11000
AS
  declare variable evnt_id integer;
begin
  /* Trigger text */
  evnt_id = gen_id(events_history_gen, 1);

  insert into events_history(event_id, event_uid, table_name, pk_name, type_op, row_id, row_uid, new_value_json, event_date, username, transaction_id)
  values (:evnt_id, uuid_to_char(gen_uuid()),  'ORDERS', 'ORDER_ID', 'I', old.UNIT_ID, old.UNIT_UID, 'insert information', current_timestamp, current_user,  current_transaction);
end
^

SET TERM ; ^


SET TERM ^ ;
CREATE OR ALTER TRIGGER ORG_STRUCTURE_EVNT_HST_AU FOR ORG_STRUCTURE
ACTIVE AFTER UPDATE POSITION 12000
AS
  declare variable evnt_id integer;
begin
  /* Trigger text */
  evnt_id = gen_id(events_history_gen, 1);

  insert into events_history(event_id, event_uid, table_name, pk_name, type_op, row_id, row_uid, new_value_json, event_date, username, transaction_id)
  values (:evnt_id, uuid_to_char(gen_uuid()),  'ORDERS', 'ORDER_ID', 'U', old.UNIT_ID, old.UNIT_UID, 'update information', current_timestamp, current_user,  current_transaction);
end
^

SET TERM ; ^

In the events history table I found something interesting. Insert log comes before update log in the same transaction for one row. Two records have equal transaction_id and equal row_id, but event_id for the update log is less than event_id for insert log. How is that possible? It seems that insert then update was executed inside transaction for one and the same record but triggers logged update then insert. I need them to be logged properly: log insert then update. How can I fix that? Why event_id generator doesn't guarantee execution order of the triggers? How can I guarantee that consecutive updates for one and the same object will be logged as they follows in the transaction block?


Solution

  • Since you have an AFTER INSERT trigger that updates the row that was just inserted, the sequence of events is as follows:

    1. The row is inserted

    2. The AFTER INSERT trigger fires and performs an UPDATE.

    3. The AFTER UPDATE trigger fires and logs the update

    4. The AFTER INSERT trigger fires and logs the insert

    As a result, you see the update before the insert in the log.

    To resolve this issue, you need to set the trigger positions so that the logging trigger fires before the updating trigger.