自治事务中的 Oracle DDL

Posted

技术标签:

【中文标题】自治事务中的 Oracle DDL【英文标题】:Oracle DDL in autonomous transaction 【发布时间】:2010-03-01 02:35:24 【问题描述】:

我需要在 Oracle 数据库上执行一堆(最多约 1000000 条)sql 语句。这些语句最终应该导致引用一致的状态,如果发生错误,所有语句都应该回滚。这些陈述没有参考顺序。因此,如果启用了外键约束,则其中一个语句可能会导致外键违规,即使此违规将通过稍后执行的语句来修复。

我尝试先禁用外键,然后在执行所有语句后启用它们。我认为当发生实际的外键违规时我可以回滚。不过我错了,我发现 Oracle 中的每个 DDL 语句都以提交开头,因此无法以这种方式回滚语句。这是我禁用外键的脚本:

begin 
  for i in (select constraint_name, table_name from user_constraints
            where constraint_type ='R' and status = 'ENABLED') 
    LOOP execute immediate 'alter table '||i.table_name||' disable constraint 
                           '||i.constraint_name||''; 
  end loop;
end;

经过一番研究,我发现建议在自治事务中执行 DDL 语句,就像在本例中一样。所以我尝试在自治事务中运行 DDL 语句。这导致了以下错误:

ORA-00054: 资源繁忙并使用指定的 NOWAIT 获取

我猜这是因为主事务在表上仍然有 DDL 锁。

我在这里做错了什么,或者有没有其他方法可以使这个场景起作用?

【问题讨论】:

【参考方案1】:

有几种可能的方法。

首先要考虑的是,您在表格级别所做的任何事情都将应用于使用该表格的所有会话。如果您没有对该表的独占访问权限,您可能不想删除/重新创建约束,或禁用/启用它们。

要考虑的第二件事是,您可能不想回滚一百万次插入/更新。回滚可能很慢。

通常我会加载到一个临时表中。然后从临时表执行单个 INSERT 到目标表。作为一条语句,Oracle 将在最后应用所有检查约束。

如果您无法通过临时表(例如更新现有数据),请在开始之前设置约束deferrable initially immediate。然后,在您的会话中,

SET CONSTRAINTS emp_job_nn, emp_salary_min DEFERRED;

然后您可以应用更改,并在您提交时验证约束。

您应该熟悉DML error logging,因为它可以帮助识别任何导致违规的行。

【讨论】:

我刚刚发现了“SET CONSTRAINTS”技巧并来到这里回答我自己的问题,我看到了你的回答:)。谢谢。

以上是关于自治事务中的 Oracle DDL的主要内容,如果未能解决你的问题,请参考以下文章

Oracle与SQL自治事务

ABAP 中的自治事务模拟

Oracle自治事务实际用例

自治事务在 Oracle 中有自己的会话吗?

快讯:Oracle自治事务处理数据库发布和19c路线图

oracle 触发器自治事务