【问题标题】:Oracle 12c using onDelete Trigger on Table with foreign key and onDelete cascade setNull throws ORA-00600: Internal Errorcode, Arguments: [13001]Oracle 12c 在具有外键和 onDelete 级联 setNull 的表上使用 onDelete 触发器抛出 ORA-00600:内部错误代码,参数:[13001]
【发布时间】:2020-01-12 10:40:43
【问题描述】:

.

你好群体智能,这是问题所在,如果没有 StackOverflow 人群的一点帮助,我似乎无法解决 :)

鉴于此 Oracle 数据库

  • Oracle Database 12c 企业版版本 12.1.0.2.0 - 64 位
  • 生产 PL/SQL 版本 12.1.0.2.0 - 生产
  • “CORE 12.1.0.2.0 Production”TNS for Solaris:版本 12.1.0.2.0 -
  • 生产 NLSRTL 版本 12.1.0.2.0 - 生产

还有这个 DDL 和数据:

CREATE TABLE TR_TEST_HIST ( 
    AUDIT_EVENT_TIMESTAMP date  NOT NULL,
    AUDIT_EVENT_TYPE     char(1)  NOT NULL,
    ID                   number(19)  NOT NULL,
    BUSINESS_KEY         varchar2(255)  NOT NULL,
    LINKED_ID            number(19)  
 );

CREATE INDEX PK_TR_TEST_0 ON TR_TEST_HIST ( ID );

CREATE INDEX IDX_TR_TEST_0 ON TR_TEST_HIST ( LINKED_ID );

CREATE TABLE TR_TEST ( 
    ID                   number(19)  NOT NULL,
    BUSINESS_KEY         varchar2(255)  NOT NULL,
    LINKED_ID            number(19)  ,
    CONSTRAINT PK_TR_TEST PRIMARY KEY ( ID ) 
 );

CREATE INDEX IDX_TR_TEST ON TR_TEST ( LINKED_ID );

CREATE OR REPLACE TRIGGER TR_TEST_AUDIT_TRIGGER
                                BEFORE DELETE OR UPDATE ON TR_TEST
                                FOR EACH ROW
                              DECLARE
                                VAR_CHANGE_TYPE CHAR(1);
                              BEGIN
                                IF UPDATING THEN VAR_CHANGE_TYPE := 'U'; ELSE VAR_CHANGE_TYPE := 'D'; END IF;
                                INSERT INTO TR_TEST_HIST (AUDIT_EVENT_TIMESTAMP,
AUDIT_EVENT_TYPE,
BUSINESS_KEY,
ID,
LINKED_ID) VALUES (CURRENT_TIMESTAMP,
VAR_CHANGE_TYPE,
:OLD.BUSINESS_KEY,
:OLD.ID,
:OLD.LINKED_ID);
                              END TR_TEST_AUDIT_TRIGGER;

ALTER TABLE TR_TEST ADD CONSTRAINT FK_TR_TEST_LINKED FOREIGN KEY ( LINKED_ID ) REFERENCES TR_TEST( ID ) ON DELETE SET NULL;

INSERT INTO TR_TEST( ID, BUSINESS_KEY, LINKED_ID ) VALUES ( 4, 'entry_4', 3 ); 
INSERT INTO TR_TEST( ID, BUSINESS_KEY, LINKED_ID ) VALUES ( 3, 'entry_3', null ); 
INSERT INTO TR_TEST( ID, BUSINESS_KEY, LINKED_ID ) VALUES ( 1, 'entry_1', null ); 
INSERT INTO TR_TEST( ID, BUSINESS_KEY, LINKED_ID ) VALUES ( 2, 'entry_2', 1 ); 

当我跑步时

DELETE FROM TR_TEST WHERE ID IN (1, 2);

语句执行失败并出现此错误

[2019-09-10 18:01:51] [60000][600] ORA-00600:内部费勒代码, 参数:[13001], [], [], [], [], [], [], [], [], [], [], [] [2019-09-10 18:01:51] java.lang.RuntimeException:错误:600, 位置:12,Sql = DELETE FROM TR_TEST WHERE ID IN (1, 2), OriginalSql = DELETE FROM TR_TEST WHERE ID IN (1, 2),错误消息 = ORA-00600:内部 Fehlercode,参数:[13001],[],[],[],[], [], [], [], [], [], [], []'

对于发生的错误消息,如果审计触发器是 BEFORE DELETE 或 AFTER DELETE,则没有区别。

但是一个接一个地删除所有内容并正确填充审计表

DELETE FROM TR_TEST WHERE ID IN (1);
DELETE FROM TR_TEST WHERE ID IN (2);

除了删除没有 WHERE 子句的所有内容,这也正确填充了审计表

DELETE FROM TR_TEST;

如果将外键级联规则更改为 doNothing,审计触发器也可以工作,但这不是这里想要的行为。

是我做错了什么,还是这是一个真正的 Oracle 错误?你知道任何解决方法吗?

感谢您的帮助, 马吕斯

【问题讨论】:

  • ORA-00600 是 Oracle 针对未处理的设计副作用(即 Oracle 错误)的标准代码。标准建议是,您需要联系 Oracle 支持。这些事情取决于操作系统平台、数据库版本、补丁级别等。除非这是常见的事情——谷歌建议在这种情况下不是——我们几乎无法为您提供建议。如果您没有支持合同,您可能会不走运。你的代码没有什么过分的地方,从表面上看它应该可以工作。
  • 您好 APC,感谢您的评论,我要求我的客户提交错误报告,如果我得到答复,请随时通知我们。如果问题也发生在其他人身上,我仍然会感兴趣吗?我对这个错误甚至存在感到有点困惑,因为对我来说似乎并不少见,将一些审计触发器与一些foreignKey级联结合使用......

标签: oracle foreign-keys database-trigger cascade ora-00600


【解决方案1】:

我已在我的 Oracle XE 18c 上对此进行了测试,并重现了该问题。有好消息也有坏消息。好消息是我想我知道导致错误的原因。坏消息是你不会喜欢它。

线索在于触发器投掷 ORA-00600 所需的时间。很长时间了。这通常是递归或死锁超时的指标。这就是我认为这里发生的事情:当您删除记录时,ON DELETE SET NULL 子句会执行 update。这会导致触发器再次触发(因为它触发了before delete or update),这会执行另一个更新并触发触发器,依此类推。最终事务以 ORA-00600 失败。如果我们放弃该外键约束,不仅删除成功,它就这样完成了!。根本没时间。

所以问题肯定是 ON DELETE SET NULL 子句。只是在一条语句中删除多行会导致 Oracle 熔断。当我们可以单独删除每一行时,这应该没有什么区别,但确实如此。这就是使它成为错误的原因。

无论如何,至少你有一个可重现的测试用例:支持喜欢那些。

【讨论】:

  • 感谢您抽出宝贵时间进行验证。让我们看看他们是怎么做的。
  • 据我所知,单个触发器仅在它引用(以任何方式 - 即使剥离为单个 dbms_output 调用):OLD.LINKED_ID 时才会导致错误。这当然是被清空的列。有趣的。虽然这么说,但它在 11.2.0.4 中对我来说也很快失败了,所以可能发生的不止一件事......(顺便说一下,解决方法在 11gR2 中有效。)
  • 是的,刚才。不幸的是,它对我不起作用,但这可能可以通过您最新的 Oracle 版本来解释。尽管如此,它仍然可以帮助其他人。编辑:我需要几秒钟才能失败
  • 我可以确认 Alex 测试,忽略 LINKED_ID :OLD.LINKED_ID 的映射,触发器在单独的触发器以及用于插入和更新的组合触发器中都能正常工作。
  • 唉,两个触发器解决方案没有解决问题。我的代码中有一个错误,太尴尬了,无法承认 ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
  • 2013-07-06
  • 1970-01-01
  • 2019-03-05
  • 1970-01-01
  • 2020-07-10
  • 2017-09-14
相关资源
最近更新 更多