postgresql - postgresql中级联触发器的执行顺序

标签 postgresql triggers

我想知道 PostgreSQL (9.3) 中 FK 的触发器的执行/触发顺序,涉及孙表,更新级联

这是我所拥有的:

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;

我还有一个关于发票的自定义更新触发器(谁的名字以 S 开头,在 RI_ 之后)。此触发器汇总发票金额。我的实际更新语句更改了 invoice_id,它向下传播到子孙。

问题是,在我的自定义触发器中/期间,Invoice_Lines 的 invoice_id 已经更改,但孙子 Invoice_Line_Taxes 没有。

我已经使用 RAISE 从自定义触发器中转储了行:

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

有什么想法吗?有人知道我在哪里可以获得有关执行顺序的官方文件吗?我曾尝试寻找有关此的详细文档,但我发现的只是顺序是按字母顺序排列的。也许如果我找到关于订单的具体细节,我可以围绕它构建一些东西。但现在,我会基于猜测工作。

谢谢。

最佳答案

trigger的执行顺序确实是字母顺序的,这里要理解为ASCII字符串顺序,"0" < "A" < "_" < "a" ,同时记住 "A3" < "a1" < "a10" < "a2" .

当你想强制以特定顺序执行时,为触发器名称添加前缀会更简单,例如(当标识符以数字开头时请注意双引号):

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

旁白:

  • 如果您的应用依赖于按特定顺序触发的触发器,或级联更新发票 ID,这可能表明您的架构、设计或代码流中存在问题.
  • 如果没有记错的话,外键会在内部强制执行为约束触发器,因此如果您依赖它们来实现应用程序逻辑,触发器触发的顺序可能会影响您。
  • 根据经验,避免让触发器对触发它们的表产生副作用,无论是直接还是间接。此规则的唯一异常(exception)是在触发器影响触发它们的行之前。任何其他方法都会产生难以修复的错误。

FWIW,我最好的猜测是你的实际问题是你有两个或三个这样的问题,而 MVCC 对你不利。即,触发器可能使 PG 将原始行标记为死行并插入一个新的事件行;随后的触发器(例如级联更新?)然后使 PG 也将新的事件行标记为已死,从而导致另一个事件行中包含意外数据,并且该术语可能会触发进一步的触发器以产生进一步的副作用。

换句话说,你的加薪通知不是观察最后更新的行,而是观察一个被一个或多个后续更新压扁的中间行。观察 ctid 所涉及的行的列应该揭示这一点,如果这确实是正在发生的事情。

最后,请注意 explain analyze将显示触发器在目标表上执行的顺序。 (上次我尝试过,它没有显示下坡的级联触发器,但这在最近的版本中可能已经改变。)使用该命令在调试触发器交互或识别性能问题时会很有帮助。

关于postgresql - postgresql中级联触发器的执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27259648/

相关文章:

ruby-on-rails - Rails ActiveRecord 铲运算符 (<<) 更新未成功,日志中无异常

mysql - 根据其他表 mySQL 中的最低排名属性更新表上的属性

MySQL触发数据拷贝

mysql - 如何修复未删除的触发器

javascript - 按钮触发器没有被调用

python - 如何在 Django 上更快地检索计数对象?

postgresql - 按用户比较事件日期

postgresql - 在以前的某个时间点执行查询

编辑文件后的 Linux 触发器

Asp.NET Core 后台服务应用