Quantcast
Channel: Mohamed Houri’s Oracle Notes
Viewing all articles
Browse latest Browse all 224

Indexed virtual column and DML error logging : ORA-03113: end-of-file on communication channel

$
0
0

This is a brief note to show you that when combining virtual column and DML error logging you might be in trouble as I have been.  First the model


create table t1(n1 number, dat1 timestamp(6));

alter table t1 add virt_n1 generated always as (case when dat1 is null then n1 else null end) virtual;

create index ind_virt_n1 on t1(virt_n1);

create table t2(n1 number, n2 number);

insert into t1 (N1,DAT1) values (1067597,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (1067597,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (1067597,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (1067597,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (1067597,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (36869,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (36869,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (170012,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (170012,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (170012,to_timestamp('05-AUG-13 10.44.09.456703000 AM','DD-MON-RR HH.MI.SS.FF AM'));
insert into t1 (N1,DAT1) values (170012,null);

insert into t2 select distinct n1, n1+1 from t1;

commit;

exec dbms_errlog.create_error_log (dml_table_name => 't1');

I have created two tables, t1 and t2.  I enriched t1 with a virtual column (virt_n1) and a non unique index (ind_virt_n1) on this virtual column. And finally, I create a DML error logging table (err$_t1) in order to log rejected records when inserting into t1;

And now the problem

insert into t1
    (n1
    ,dat1)
select
   t2.n1
   ,systimestamp
from t2
log errors into ERR$_t1 reject limit unlimited;
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel

It took me a couple of minutes to figure out that this error is due the DML logging error because when I get rid of this error logging the insert works perfectly

insert into t1
(n1
,dat1)
select  t2.n1
,systimestamp
from t2;

3 rows created.

But wait; I was not going to let down my DML error just because of this end-of-file on communication channel?  I was curious to know the reason that impeaches my insert to work when combined with the DML error logging. The way I did approached this issue is to ask myself what is the difference between the actual situation and the old and many situations where I did smoothly used the DML error logging. You might have already guessed the answer because it is in the title of this blog article: virtual column. So, I immediately described the err$_t1 which shows the presence of the virtual column


SQL> desc err$_t1
Name                            Null?    Type
------------------------------- -------- ---------------
1      ORA_ERR_NUMBER$                          NUMBER
2      ORA_ERR_MESG$                            VARCHAR2(2000)
3      ORA_ERR_ROWID$                           ROWID
4      ORA_ERR_OPTYP$                           VARCHAR2(2)
5      ORA_ERR_TAG$                             VARCHAR2(2000)
6      N1                                       VARCHAR2(4000)
7      DAT1                                     VARCHAR2(4000)
8      VIRT_N1                                  VARCHAR2(4000) -- virtual column

By simply dropping the virtual column from the err$_t1 the insert works perfectly  in the presence of DML error logging table as shown below:

alter table err$_t1 drop column virt_n1;
Table altered.

insert into t1
(n1
,dat1)
select  t2.n1
,systimestamp
from t2
log errors into ERR$_t1 reject limit unlimited;

3 rows created.

I was still curious to know why the presence of a virtual column in the error table impeaches things to work correctly. There might be another reason. This is why I started as an electrician who is having an electrical problem in his installation but doesn’t know exactly which is the culprit electrical devise is.  I modeled my real life tables and started dropping object by object (foreign key, unique key, index) until I found the culprit object:  ind_virt_n1 the index on the virtual column.

If you re-create the model presented above and, this time, drop the index ind_virt_n1 and let the virtual column in the err$_t1 table the insert will this time work perfectly as shown below:

drop index ind_virt_n1;
Index dropped.

insert into t1
    (n1
    ,dat1)
select
    t2.n1
   ,systimestamp
from t2
log errors into ERR$_t1 reject limit unlimited;

3 rows created.

The bottom line of this article is to show that mixing indexed virtual column and DML error logging might not work without error. In my case I opted for dropping the virtual column from the err$_t1 instead of dropping the virtual index because of the performance gain this index brings to my application.



Viewing all articles
Browse latest Browse all 224

Trending Articles