变异表错误的原因和解决方法是什么?

par*_*and 12 trigger oracle plsql

我知道变异表错误是由设计缺陷或有问题的查询引起的。

最近将一个旧查询投入生产,它引发了一个变异表错误。我们的 DBA 解决了这个问题,但我们不知道如何解决。

究竟是什么导致了变异表错误,我们的 DBA 将如何解决这个问题?

Vin*_*rat 17

发生变异表错误的最可能原因是误用触发器。下面是一个典型的例子:

  1. 您在表 A 中插入一行
  2. 表 A 上的触发器(针对每一行)对表 A 执行查询,例如计算汇总列
  3. Oracle 抛出 ORA-04091:表 A 正在发生变异,触发器/函数可能看不到它

这是一种预期和正常的行为,Oracle 希望保护您免受自己的伤害,因为 Oracle 保证:

  • (i) 每个语句都是原子的(即要么失败要么完全成功)
  • (ii) 每个语句都看到一致的数据视图

当您编写这种触发器时,很可能您希望查询 (2) 看到插入到 (1) 上的行。这将与上述两点矛盾,因为更新尚未完成(可能有更多行要插入)。

Oracle可以返回与语句开始之前的某个时间点一致的结果,但是从我看到的大多数尝试实现此逻辑的示例中,人们将多行语句视为一系列连续步骤,并期望语句 [2] 以查看前面步骤所做的更改。Oracle 无法返回预期结果并因此引发错误。

进一步阅读:Ask Tom 上的“变异表”

如果我怀疑变异表错误的原因是触发器,那么避免错误的一种方法是将逻辑从触发器移到过程中。


Lei*_*fel 9

一个变异表时的声明导致触发器触发和触发器引用导致触发器表中出现。避免此类问题的最佳方法是不使用触发器,但我怀疑 DBA 没有花时间这样做。他可以执行以下操作之一: