2014-12-02 46 views
1

我想了解一下執行/激活觸發器的順序與UPDATE CASCADE FKS,關於孫表,在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_Lines的invoice_id已經更改,但不是用於孫子Invoice_Line_Taxes。

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

所以我想知道,有什麼關於這觸發執行順序:

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

觸發後:

我從自定義觸發內使用RAISE傾倒行級聯觸發器?

我會認爲這樣的事情:

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" ... 

旁白:

  • 如果您的應用程序依賴於特定的順序觸發器被解僱,或級聯更新發票IDS,它可能是您的架構,設計或代碼流中出現錯誤的標誌。
  • 如果內存服務,外鍵作爲約束觸發器在內部強制執行,所以如果您依賴應用程序邏輯,則觸發器觸發的順序可能會出現並咬你。
  • 作爲一個經驗法則,避免讓觸發器對直接或間接觸發它們的表有副作用。此規則唯一的例外是在觸發器觸發影響行的觸發器之前。其他任何東西都將很難修復錯誤。

FWIW,我最好的猜測是你的實際問題是你有兩個或三個這些點和MVCC對你不利。也就是說,觸發器可能會使PG將原始行標記爲死亡並插入新的活動行;隨後的觸發(例如,級聯更新?)然後使PG標誌新活行如死,這樣會造成另一種生活排在它意想不到的數據,而且在長期可燒製進一步副作用進一步觸發。

換句話說,你的加薪通知沒有觀測到最後更新的行,但得到由一個或多個後續更新壓扁的中介之一。觀察所涉及的行的ctid列應該揭示這一點,如果這確實是怎麼回事。

最後,注意explain analyze將顯示在觸發獲得對目標表執行順序。 (最後我嘗試了一下,它並沒有顯示級聯觸發器下坡,但在最近的版本中可能會有所變化。)在調試觸發器交互或識別性能問題時,使用該命令會很有幫助。

+0

謝謝。解釋分析提示有很大幫助。在此之前,我創建了一個與之相呼應的小觸發器,用於評估觸發器執行的順序。 – user4317541 2014-12-31 21:03:08

0

在涉及的表格上設置了一些觸發器之後,我們發現了一系列事件(但是,由於上述答案,EXPLAIN ANALYSE更容易實現):

關於發票
  • 發票上的所有觸發器
    1. 更新被解僱,爲了
      • 一些觸發的影響對Invoices_Lines更新(子表)
    2. 上Invoice_Lines所有觸發器被解僱,爲了(但所有的父母觸發器完成後)
      • 一些觸發的影響對Invoice_Line_Taxes更新(孫表)
    3. 上Invoice_Line_Taxes所有觸發器被解僱, (但畢竟其父觸發器完成)

    因此,觸發器的命名隻影響其「本地」執行順序。

    無論如何,我最終設置觸發器運行INITIALLY DEFERRED,並完成工作。雖然是的,但我同意,以這種方式使用觸發器是脆弱的。