When you create a replication between two tables, a snapshot log for your materialized views, etc. Oracle creates and manages internal triggers that execute SQL statements. For example, when you insert a row in a table with a snapshot log, sql statements are executed in the related snapshot log table (MLOG$ table).
But if you trace it with 10046 event, nothing will appear in the trace file.
SQL> create materialized view log on OBJ$CLONE;
Materialized view log created.
SQL> select * from mlog$_OBJ$CLONE;
no rows selected
SQL> @10046_on.sql
Session altered.
SQL> delete from OBJ$CLONE where obj#=3000;
1 row deleted.
SQL> insert into OBJ$CLONE select * from sys.obj$ where obj#=3000;
1 row created.
SQL> commit;
Commit complete.
SQL> @10046_off.sql
The tracefile doesn’t mention any DML operation on the table MLOG$_OBJ$CLONE (see the tkprof output below):
SQL ID: 46m19q6258mvs Plan Hash: 4136978372
SELECT /* OPT_DYN_SAMP */ /*+ ALL_ROWS IGNORE_WHERE_CLAUSE
NO_PARALLEL(SAMPLESUB) opt_param('parallel_execution_enabled', 'false')
NO_PARALLEL_INDEX(SAMPLESUB) NO_SQL_TUNE */ NVL(SUM(C1),0), NVL(SUM(C2),0)
FROM
(SELECT /*+ NO_PARALLEL("MLOG$_OBJ$CLONE") FULL("MLOG$_OBJ$CLONE")
NO_PARALLEL_INDEX("MLOG$_OBJ$CLONE") */ 1 AS C1, 1 AS C2 FROM
"LAURENT"."MLOG$_OBJ$CLONE" "MLOG$_OBJ$CLONE") SAMPLESUB
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 0.00 0.05 0 0 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 14 0 2
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 6 0.00 0.05 0 14 0 2
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: SYS (recursive depth: 2)
Number of plan statistics captured: 2
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
1 1 1 SORT AGGREGATE (cr=7 pr=0 pw=0 time=204 us)
4 4 5 TABLE ACCESS FULL MLOG$_OBJ$CLONE (cr=7 pr=0 pw=0 time=105 us cost=2 size=0 card=82)
********************************************************************************
SQL ID: 2ya3sb8sagzxw Plan Hash: 3957508444
delete from OBJ$CLONE
where
obj#=3000
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.01 0.07 0 8 0 0
Execute 1 0.00 0.00 0 3 8 1
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.01 0.07 0 11 8 1
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 90
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 DELETE OBJ$CLONE (cr=3 pr=0 pw=0 time=372 us)
1 1 1 INDEX UNIQUE SCAN PK_OBJ$CLONE (cr=2 pr=0 pw=0 time=34 us cost=1 size=13 card=1)(object id 127619)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 3.68 3.68
********************************************************************************
SQL ID: 4n7u7f6u7kd2y Plan Hash: 1218588913
insert into OBJ$CLONE select * from sys.obj$ where obj#=3000
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 8 4 0
Execute 1 0.00 0.00 0 5 8 1
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.00 0.00 0 13 12 1
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 90
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
0 0 0 LOAD TABLE CONVENTIONAL (cr=5 pr=0 pw=0 time=518 us)
1 1 1 TABLE ACCESS BY INDEX ROWID OBJ$ (cr=3 pr=0 pw=0 time=75 us cost=3 size=86 card=1)
1 1 1 INDEX RANGE SCAN I_OBJ1 (cr=2 pr=0 pw=0 time=46 us cost=2 size=0 card=1)(object id 36)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 2.44 2.44
********************************************************************************
SQL ID: 23wm3kz7rps5y Plan Hash: 0
commit
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 1 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 2 0.00 0.00 0 0 1 0
Misses in library cache during parse: 0
Parsing user id: 90
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 4.10 4.10
********************************************************************************
but there are some datas in this table:
SQL> select * from mlog$_OBJ$CLONE;
OBJ# SNAPTIME$ D O CHANGE_VECTOR$$ XID$$
---------- --------- - - ------------------------------ ----------
3000 01-JAN-00 D O 000000 5.6296E+15
3000 01-JAN-00 I N FEFFFF 5.6296E+15
And internal triggers is created to do this:
SQL> select * from user_internal_triggers;
TABLE_NAME INTERNAL_TRIGGER_TY
------------------------------ -------------------
OBJ$CLONE MVIEW LOG
By searching in USER_INTERNAL_TRIGGERS code, we can see that this view references internal triggers on ‘DEFERRED RPC QUEUE’, ‘MVIEW LOG’, ‘UPDATABLE MVIEW LOG’ and ‘CONTEXT’. (based on the TAB$ table’s TRIGFLAG column).
select dbms_metadata.get_ddl('VIEW','USER_INTERNAL_TRIGGERS','SYS') ddl from dual
DDL
------------------------------------------------------------------------------------------------------------------------
CREATE OR REPLACE FORCE VIEW "SYS"."USER_INTERNAL_TRIGGERS" ("TABLE_NAME", "INTERNAL_TRIGGER_TYPE") AS
select o.name, 'DEFERRED RPC QUEUE'
from sys.tab$ t, sys.obj$ o
where o.owner# = userenv('SCHEMAID')
and t.obj# = o.obj#
and bitand(t.trigflag,1) = 1
union
select o.name, 'MVIEW LOG'
from sys.tab$ t, sys.obj$ o
where o.owner# = userenv('SCHEMAID')
and t.obj# = o.obj#
and bitand(t.trigflag,2) = 2
union
select o.name, 'UPDATABLE MVIEW LOG'
from sys.tab$ t, sys.obj$ o
where o.owner# = userenv('SCHEMAID')
and t.obj# = o.obj#
and bitand(t.trigflag,4) = 4
union
select o.name, 'CONTEXT'
from sys.tab$ t, sys.obj$ o
where o.owner# = userenv('SCHEMAID')
and t.obj# = o.obj#
and bitand(t.trigflag,8) = 8
If you want to trace what is really done by the internal trigger, you have a bunch of undocumented events that will trace specific triggers (Note there are events for repcat or synchronous replication for which there is no trigflag definition in USER_INTERNAL_TRIGGERS view code):
10302, 00000, "trace create or drop internal trigger"
// *Document: NO
// *Cause:
// *Action:
10303, 00000, "trace loading of library cache for internal triggers"
// *Document: NO
// *Cause:
// *Action:
10304, 00000, "trace replication trigger"
// *Document: NO
// *Cause:
// *Action:
10305, 00000, "trace updatable materialized view trigger"
// *Document: NO
// *Cause:
// *Action:
10306, 00000, "trace materialized view log trigger"
// *Document: NO
// *Cause:
// *Action:
10307, 00000, "trace RepCat execution"
// *Document: NO
// *Cause:
// *Action:
10308, 00000, "replication testing event"
// *Document: NO
// *Cause:
// *Action:
10309, 00000, "Trigger Debug event"
// *Document: NO
// *Cause:
// *Action:
// *Comment: This event replaces the earlier event number 10250
// which had multiple definitions
10310, 00000, "trace synchronous change table trigger"
// *Document: NO
// *Cause:
// *Action:
I have chosen the 10306 event to trace internal triggers on Materialized view log (but you can use others depending on what you want to trace):
SQL> create materialized view log on OBJ$CLONE;
Materialized view log created.
SQL> select * from user_internal_triggers;
TABLE_NAME INTERNAL_TRIGGER_TY
------------------------------ -------------------
OBJ$CLONE MVIEW LOG
SQL> alter session set events '10306 trace name context forever, level 10';
Session altered.
SQL> delete from OBJ$CLONE where obj#=3000;
1 row deleted.
SQL> insert into OBJ$CLONE select * from sys.obj$ where obj#=3000;
1 row created.
SQL> commit;
Commit complete.
The related trace file shows SQL statements now executed on MLOG$_OBJ$CLONE table:
kntgslm()+
ccl_kntsl = 1
kntzcid =
1
lcc_kntsl = 0
kntzlcs =
kntzlcm =
cpk_kntsl = 1
pkc_kntsl =
1
flg_kntsl = 270434
len_kntsl = 220
sql_kntsl = INSERT /*+ IDX(%d) */ INTO "LAURENT"."MLOG$_OBJ$CLONE" (dmltype$$,old_new$$,snaptime$$,change_vector$$,xid$$,"OBJ#") VALUES (:d,:o,to_date('4000-01-01:00:00:00','YYYY-MM-DD:HH24:MI:SS'),:c,:x%s,:1)
len2_kntsl = 0
sql2_kntsl =
kntgslm()-
kntkca()
ccl_kntsl = 1
kntzcid =
1
lcc_kntsl = 0
kntzlcs =
kntzlcm =
cpk_kntsl = 1
pkc_kntsl =
1
flg_kntsl = 270434
len_kntsl = 220
sql_kntsl = INSERT /*+ IDX(%d) */ INTO "LAURENT"."MLOG$_OBJ$CLONE" (dmltype$$,old_new$$,snaptime$$,change_vector$$,xid$$,"OBJ#") VALUES (:d,:o,to_date('4000-01-01:00:00:00','YYYY-MM-DD:HH24:MI:SS'),:c,:x%s,:1)
len2_kntsl = 0
sql2_kntsl =
kntxslt()
ccl_kntsl = 1
kntzcid =
1
lcc_kntsl = 0
kntzlcs =
kntzlcm =
cpk_kntsl = 1
pkc_kntsl =
1
flg_kntsl = 270434
len_kntsl = 220
sql_kntsl = INSERT /*+ IDX(%d) */ INTO "LAURENT"."MLOG$_OBJ$CLONE" (dmltype$$,old_new$$,snaptime$$,change_vector$$,xid$$,"OBJ#") VALUES (:d,:o,to_date('4000-01-01:00:00:00','YYYY-MM-DD:HH24:MI:SS'),:c,:x%s,:1)
len2_kntsl = 0
sql2_kntsl =
*** 2013-01-16 11:53:21.065
kntkca()
ccl_kntsl = 1
kntzcid =
1
lcc_kntsl = 0
kntzlcs =
kntzlcm =
cpk_kntsl = 1
pkc_kntsl =
1
flg_kntsl = 270434
len_kntsl = 220
sql_kntsl = INSERT /*+ IDX(%d) */ INTO "LAURENT"."MLOG$_OBJ$CLONE" (dmltype$$,old_new$$,snaptime$$,change_vector$$,xid$$,"OBJ#") VALUES (:d,:o,to_date('4000-01-01:00:00:00','YYYY-MM-DD:HH24:MI:SS'),:c,:x%s,:1)
len2_kntsl = 0
sql2_kntsl =
kntxslt()
ccl_kntsl = 1
kntzcid =
1
lcc_kntsl = 0
kntzlcs =
kntzlcm =
cpk_kntsl = 1
pkc_kntsl =
1
flg_kntsl = 270434
len_kntsl = 220
sql_kntsl = INSERT /*+ IDX(%d) */ INTO "LAURENT"."MLOG$_OBJ$CLONE" (dmltype$$,old_new$$,snaptime$$,change_vector$$,xid$$,"OBJ#") VALUES (:d,:o,to_date('4000-01-01:00:00:00','YYYY-MM-DD:HH24:MI:SS'),:c,:x%s,:1)
len2_kntsl = 0
sql2_kntsl =
You can notice we have 5 instructions in sql_kntsl for 2 rows modified. Each statement seems to be controlled by 2 internal functions: kntkca() and kntxslt(). There is one more function used to start this sequence kntgslm().
If I trace only one DML instruction in my OBJ$CLONE table, the result is one call to kntgslm() followed by a call to kntkca() and kntxslt().
So the sequence might start with a call to kntgslm followed by a call to kntkca() and kntxslt() per row in the source table.
Finally, there’s a last problem: the sql text mentioned in sql_kntsl. It seems to be incomplete because of %d or %s in text but with those events, we can find in the sql statements executed we didn’t fin in the sql trace of the original statement.
Like this:
Like Loading...
Related
Another great submit thanks for the tips as well as very good study.