2014-12-02 3 views
1

Я задаюсь вопросом о выполнении/запала порядок триггеров для ФКС с UPDATE CASCADE, касающиеся таблиц внучат, в PostgreSQL (9,3)Выполнение заказа каскадных триггеров в PostgreSQL

Вот что у меня есть:

Parent:  Invoices   (invoice_id) 
Child:  Invoice_Lines  (invoice_id, line_nbr) 
Grandchild: Invoice_Line_Taxes (invoice_id, line_nbr, tax) 

Invoice_Lines has FOREIGN KEY (invoice_id) REFERENCES Invoices ON UPDATE CASCADE; 
Invoice_Line_Taxes has FOREIGN KEY (invoice_id, line_nbr) REFERENCES Invoice_Lines ON UPDATE CASCADE; 

У меня также есть пользовательский триггер UPDATE для счетов-фактур (имя начинается с S, которое появляется после RI_). Этот триггер суммирует суммы счетов. И мой фактический оператор обновления изменяет invoice_id, который распространяется до ребенка и внука.

Неисправность в/во время моего настраиваемого триггера invoice_id для Invoice_Lines уже изменена, но не для внука Invoice_Line_Taxes.

Я сбросила строки внутри пользовательского триггера с помощью ПОВЫШЕНИЕ:

invoice_lines: (5,1) 
invoice_line_taxes: (-1,1,HST) 

После запуска:

SELECT * from invoice_line_taxes where invoice_id IN (5,-1); 
invoice_id | line_nbr | tax_nm 
------------+----------+-------- 
      5 |  1 | HST 

Так что я задаюсь вопросом, что такое порядок выполнения триггера по отношению к каскадные триггеры?

Я предположил бы, что-то вроде этого:

RI_on_invoices 
RI_on_invoice_lines 
S_custom_trigger 

Любые идеи? Кто-нибудь знает, где я могу получить официальную документацию по заказу на исполнение? Я пробовал найти подробную документацию об этом, но все, что я нашел, это упорядочение в алфавитном порядке. Возможно, если я найду конкретные подробности о заказе, я смогу что-то создать вокруг него. Но сейчас я буду основывать его на догадках.

спасибо.

ответ

2

Порядок выполнения триггера действительно алфавит, который вы хотите здесь понимать как строковый порядок ASCII, "0" < "A" < "_" < "a", имея в виду, что "A3" < "a1" < "a10" < "a2".

Если вы хотите принудительно выполнить выполнение в определенном порядке, проще назначить имена триггеров, например. (Обратите внимание на двойные кавычки, когда идентификаторы начинаются с номера):

create trigger _01_do_stuff ... 
create trigger "01_do_stuff" ... 

Asides:

  • Если ваше приложение использует триггеры увольняют в определенном порядке, или каскадное обновление счетов-фактур идентификаторами, он МАЕ будет признаком того, что что-то не так в вашей схеме, в вашем дизайне или в вашем потоке кода.
  • Если память используется, внешние ключи принудительно применяются в качестве триггеров ограничений, поэтому порядок, в котором срабатывает триггеры, может наступить и укусить вас, если вы полагаетесь на них для логики приложения.
  • Как правило, избегайте создания триггеров, имеющих побочные эффекты на таблицах, которые запускают их прямо или косвенно. Единственным исключением из этого правила является то, что триггеры влияют на строку, которая их запускает. Все остальное затруднит исправление ошибок.

FWIW, я думаю, что ваша фактическая проблема заключается в том, что у вас есть два или три из этих пунктов, и MVCC работает против вас. А именно, триггер, вероятно, делает PG отмечать исходную строку как мертвую и вставлять новую живую строку; последующий триггер (например,каскадное обновление?) затем делает PG отмечать, что новая живая строка также мертва, в результате появляется еще одна живая строка с неожиданными данными в ней и что в перспективе может быть запущен дальнейший триггер для дальнейших побочных эффектов.

Другими словами, ваше уведомление о повышении не наблюдает за окончательной обновленной строкой, а промежуточным, которое получает раздавленное одним или несколькими последующими обновлениями. Наблюдение за столбцом ctid строк должно показать это, если это действительно то, что происходит.

И, наконец, обратите внимание, что explain analyze покажет порядок запуска триггеров в целевой таблице. (Последнее, что я пробовал, он не показывал каскадные триггеры под гору, но это могло измениться в последних версиях.) Использование этой команды может быть полезно при отладке взаимодействий триггеров или при выявлении проблем с производительностью.

+0

спасибо. Подробный поясник объяснения помогает. До этого я создал небольшой триггер, который эхом отозвался, его вызывали, чтобы оценить порядок выполнения триггеров. – user4317541

0

После установки некоторых триггеров на столах, вовлеченных, что просто поднял уведомление о том, что они собирались назвать, я наблюдал следующую последовательность событий (хотя, благодаря ответу выше, EXPLAIN ANALYZE это достигается более легко):

  1. Обновление счетов-фактур на
  2. все триггеры на Invoices обжигают, чтобы
    • некоторые из этих триггеров влияют на обновление на Invoices_Lines (детский стол)
  3. всех триггера Invoice_Lines увольняются, в порядке (но после того, как все родительские триггера выполняются)
    • некоторые из этих триггеров влияют на обновление на Invoice_Line_Taxes (внучка таблица)
  4. всех триггеров Invoice_Line_Taxes увольняют, в порядке (но после завершения всех его родительских триггеров)

Таким образом, именование триггеров влияет только на его «локальный» порядок выполнения.

Во всяком случае, я закончил установку триггера, чтобы запустить INITIALLY DEFERRED, и это выполняет свою работу. Хотя да, я согласен, использование триггеров таким образом является незначительным.