Oracle 12c 在带有外键的表上使用 onDelete 触发器和 onDelete 级联 setNull 抛出 ORA-00600 : Internal Errorcode, 参数:[13001]

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

.

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

鉴于此 Oracle 数据库

  • Oracle Database 12c 企业版版本 12.1.0.2.0 - 64 位
  • 生产 PL/SQL 版本 12.1.0.2.0 - 生产
  • 适用于 Solaris 的“CORE 12.1.0.2.0 生产”TNS:版本 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: Interner Fehlercode, Argumente: [13001], [], [], [], [], [], [], [], [], [], [], [] [2019-09-10 18:01:51] java.lang.RuntimeException: Error : 600, Position : 12, Sql = DELETE FROM TR_TEST WHERE ID IN (1, 2), OriginalSql = DELETE FROM TR_TEST WHERE ID IN (1, 2), Error Msg = ORA-00600: Interner Fehlercode, Argumente: [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 错误?你知道有什么解决办法吗?

感谢您的帮助, 马吕斯

最佳答案

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

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

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

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

关于Oracle 12c 在带有外键的表上使用 onDelete 触发器和 onDelete 级联 setNull 抛出 ORA-00600 : Internal Errorcode, 参数:[13001],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57874752/

相关文章:

java - oracle中如何给触发器发送参数

sql - PostgreSQL 错误 : there is no unique constraint matching given keys for referenced table

java - 暂停所有正在运行的线程一段时间

sql - 如何根据另一个表中的值创建重复记录

java - Oracle/Mysql编辑记录量大,有推荐吗?

database - 无法以 Oracle 11g 中新创建的用户身份登录

windows - 使用 Perl DBI 模块或设置系统 DSN 并使用 ODBC 哪个更好?

mysql - 双向外键约束检查

mysql - 外键力独特

mysql - 创建触发器错误 : invalid syntax