Oracle 12c 在 Table 上使用带有外键的 onDelete 触发器和 onDelete 级联 setNull 抛出 ORA-00600:内部错误代码,参数:[13001]
Oracle 12c using onDelete Trigger on Table with foreign key and onDelete cascade setNull throws ORA-00600: Internal Errorcode, Arguments: [13001]
.
你好 swarm intelligence,这就是问题,如果没有 Whosebug 人群的一点帮助,我似乎无法解决 :)
鉴于此 Oracle 数据库
- Oracle Database 12c 企业版 12.1.0.2.0 版 - 64 位
- 生产 PL/SQL 版本 12.1.0.2.0 - 生产
- "CORE 12.1.0.2.0 Production" 适用于 Solaris 的 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], [], [], [], [],
[], [], [], [], [], [], []'
对于出现错误消息,审计触发器是删除前还是删除后没有区别。
但是一个接一个地删除所有内容并正确填写审计table
DELETE FROM TR_TEST WHERE ID IN (1);
DELETE FROM TR_TEST WHERE ID IN (2);
以及删除所有没有 WHERE 子句的内容,这也正确地填写了审计 table
DELETE FROM TR_TEST;
审计触发器也可以工作,如果将外键级联规则更改为 doNothing,但这不是这里想要的行为。
我是不是做错了什么,或者这是一个真正的 Oracle 错误?您知道任何解决方法吗?
感谢您的帮助,
马吕斯
我已经在我的 Oracle XE 18c 上对此进行了测试并重现了该问题。有好消息也有坏消息。好消息是我想我知道导致错误的原因。坏消息是你不会喜欢它。
线索在于触发器抛出 ORA-00600 所需的时间。很长时间了。这通常是递归或死锁超时的指示器。这就是我认为这里正在发生的事情:当您删除一条记录时,ON DELETE SET NULL 子句会执行 update。这会导致触发器再次触发(因为它会触发 before delete or update
),这会执行另一个更新并触发触发器,依此类推。最终事务失败并返回 ORA-00600。如果我们删除外键约束,不仅删除会成功,而且会像那样完成 !。没时间。
所以问题肯定出在 ON DELETE SET NULL 子句上。在一个语句中删除多行会导致 Oracle 烧毁保险丝。当我们可以单独删除每一行时,这应该没有什么不同,但确实如此。这就是使它成为错误的原因。
无论如何,至少你有一个可重现的测试用例:支持喜欢那些。
.
你好 swarm intelligence,这就是问题,如果没有 Whosebug 人群的一点帮助,我似乎无法解决 :)
鉴于此 Oracle 数据库
- Oracle Database 12c 企业版 12.1.0.2.0 版 - 64 位
- 生产 PL/SQL 版本 12.1.0.2.0 - 生产
- "CORE 12.1.0.2.0 Production" 适用于 Solaris 的 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], [], [], [], [], [], [], [], [], [], [], []'
对于出现错误消息,审计触发器是删除前还是删除后没有区别。
但是一个接一个地删除所有内容并正确填写审计table
DELETE FROM TR_TEST WHERE ID IN (1);
DELETE FROM TR_TEST WHERE ID IN (2);
以及删除所有没有 WHERE 子句的内容,这也正确地填写了审计 table
DELETE FROM TR_TEST;
审计触发器也可以工作,如果将外键级联规则更改为 doNothing,但这不是这里想要的行为。
我是不是做错了什么,或者这是一个真正的 Oracle 错误?您知道任何解决方法吗?
感谢您的帮助, 马吕斯
我已经在我的 Oracle XE 18c 上对此进行了测试并重现了该问题。有好消息也有坏消息。好消息是我想我知道导致错误的原因。坏消息是你不会喜欢它。
线索在于触发器抛出 ORA-00600 所需的时间。很长时间了。这通常是递归或死锁超时的指示器。这就是我认为这里正在发生的事情:当您删除一条记录时,ON DELETE SET NULL 子句会执行 update。这会导致触发器再次触发(因为它会触发 before delete or update
),这会执行另一个更新并触发触发器,依此类推。最终事务失败并返回 ORA-00600。如果我们删除外键约束,不仅删除会成功,而且会像那样完成 !。没时间。
所以问题肯定出在 ON DELETE SET NULL 子句上。在一个语句中删除多行会导致 Oracle 烧毁保险丝。当我们可以单独删除每一行时,这应该没有什么不同,但确实如此。这就是使它成为错误的原因。
无论如何,至少你有一个可重现的测试用例:支持喜欢那些。