我们最近已经从Oracle 10升级到Oracle 11.2。升级之后,我开始看到一个由函数而不是触发器引起的变异表错误(我以前从未见过这种错误)。这是在以前版本的Oracle中工作的旧代码。
下面是一个会导致错误的场景:
create table mutate (
x NUMBER,
y NUMBER
);
insert into mutate (x, y)
values (1,2);
insert into mutate (x, y)
values (3,4);我创造了两行。现在,通过调用以下语句,我将加倍我的行:
insert into mutate (x, y)
select x + 1, y + 1
from mutate;这对于复制错误并不是绝对必要的,但它有助于后面的演示。表的内容现在如下所示:
X,Y
1,2
3,4
2,3
4,5平安无事。现在是有趣的部分:
create or replace function mutate_count
return PLS_INTEGER
is
v_dummy PLS_INTEGER;
begin
select count(*)
into v_dummy
from mutate;
return v_dummy;
end mutate_count;
/我创建了一个函数来查询我的表并返回一个计数。现在,我将把它与INSERT语句结合起来:
insert into mutate (x, y)
select x + 2, y + 2
from mutate
where mutate_count() = 4;结果是什么呢?此错误:
ORA-04091: table MUTATE is mutating, trigger/function may not see it
ORA-06512: at "MUTATE_COUNT", line 6所以我知道是什么导致了这个错误,但是我很好奇为什么。Oracle不是在执行SELECT,检索结果集,然后执行这些结果的大容量插入吗?只有在查询完成之前已经插入了记录时,我才会期望发生变异的表错误。但如果甲骨文这么做了,之前的声明不是吗?
insert into mutate (x, y)
select x + 1, y + 1
from mutate;开始无限循环?
更新:
通过杰弗里的链接,我在甲骨文文档中找到了这个
默认情况下,Oracle保证语句级的读取一致性。单个查询返回的数据集相对于单个时间点是一致的。
在他的职位中也有作者的评论
对于SQL语句中出现的重复函数调用,人们可能会争论为什么Oracle不确保这种“语句级读取一致性”。据我所知,这可能被认为是一种错误。但这是目前的工作方式。
我是否正确地假设这种行为在Oracle版本10和11之间发生了变化?
发布于 2012-03-30 01:45:40
首先,
insert into mutate (x, y)
select x + 1, y + 1
from mutate;不会启动无限循环,因为查询将看不到在语句开始时仅存在的数据。新行只对后续语句可见。
这很好地解释了这一点:
当Oracle走出当前正在执行update语句的SQL-engine并调用该函数时,该函数--就像行后更新触发器一样--看到EMP的中间状态在update语句执行过程中是否存在。这意味着函数调用的返回值在很大程度上取决于行被更新的顺序。
发布于 2012-03-30 11:11:35
语句-级别读取一致性和事务级读取一致性“.
从手册中:
“如果选择列表包含一个函数,则数据库在语句级别应用语句级的读取一致性,用于在PL/SQL函数代码,中运行,而不是在父SQL级别中运行。例如,函数可以访问另一个用户更改和提交数据的表。在函数中每次执行SELECT时,都会建立一个新的读取一致快照”。
这两个概念在“Oracle数据库概念”中都有解释:
01/server.102/b 14220/稠密.#sthref1955 1955
->>> 更新
->>>*Section 在之后添加了OP被关闭的
规则
该技术规则由kemp先生(@jeffrey-kemp)很好地链接,Toon http://harmfultriggers.blogspot.com.au/2011/12/look-mom-mutating-table-error-without.html解释得很好,在"Pl/Sql语言引用-控制PL/SQL子程序的副作用“(您的函数违反RNDS读取不读取数据库状态)中报告了该规则:
从INSERT、UPDATE或DELETE语句调用时,该函数不能查询或修改该语句修改的任何数据库表。 如果一个函数查询或修改一个表,而该表上的DML语句调用该函数,则会发生ORA-04091 (变异表错误)。
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/subprograms.htm#CHDJJCEC
https://stackoverflow.com/questions/9935239
复制相似问题