Oracle Version: Docker Image container-registry.oracle.com/database/enterprise:19.19.0.0
Setup Script (to enable logminer)
SELECT log_mode FROM v$database;
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
SELECT log_mode FROM v$database;
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;
select supplemental_log_data_min, supplemental_log_data_pk from v$database;
I'm using logMiner to get the redo logs, while i notice this strange behavior:
- Client Side Queries:
SELECT CURRENT_SCN FROM V$DATABASE; -- 2554427
INSERT INTO t1 VALUES (1, 1);
SAVEPOINT s1;
INSERT INTO t1 VALUES (2, 2);
SELECT CURRENT_SCN FROM V$DATABASE; -- 2554481
INSERT INTO t1 VALUES (3, 3);
SELECT CURRENT_SCN FROM V$DATABASE; -- 2554528
ROLLBACK TO s1;
SELECT CURRENT_SCN FROM V$DATABASE; -- 2554565
COMMIT;
SELECT CURRENT_SCN FROM V$DATABASE; -- 2554583
- To query logMiner for all the redo logs in this transaction:
EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME => '/opt/oracle/oradata/ORCLCDB/redo01.log', OPTIONS => DBMS_LOGMNR.NEW);
EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME => '/opt/oracle/oradata/ORCLCDB/redo02.log', OPTIONS => DBMS_LOGMNR.ADDFILE);
EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME => '/opt/oracle/oradata/ORCLCDB/redo03.log', OPTIONS => DBMS_LOGMNR.ADDFILE);
EXEC DBMS_LOGMNR.START_LOGMNR(STARTSCN => 2554427, ENDSCN => 2554565, OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);
SELECT SCN, XID, XIDUSN, XIDSLT, XIDSQN, SQL_REDO, ROLLBACK FROM V$LOGMNR_CONTENTS WHERE TABLE_NAME = 'T1';
This gives me:
SCN XID XIDUSN XIDSLT XIDSQN SQL_REDO ROLLBACK
__________ ___________________ _________ _________ _________ _________________________________________________________________ ___________
2554454 D4001F0014000000 212 31 20 insert into "MY_USER"."T1"("PK","V") values ('1','1'); 0
2554475 D4001F0014000000 212 31 20 insert into "MY_USER"."T1"("PK","V") values ('2','2'); 0
2554524 D4001F0014000000 212 31 20 insert into "MY_USER"."T1"("PK","V") values ('3','3'); 0
2554545 D4001F0014000000 212 31 20 delete from "MY_USER"."T1" where ROWID = 'AAASkaAAHAAAAFcAAC'; 1
2554545 D4001F0014000000 212 31 20 delete from "MY_USER"."T1" where ROWID = 'AAASkaAAHAAAAFcAAB'; 1
- To query logMiner for only the ROLLBACK TO s1 stmt:
EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME => '/opt/oracle/oradata/ORCLCDB/redo01.log', OPTIONS => DBMS_LOGMNR.NEW);
EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME => '/opt/oracle/oradata/ORCLCDB/redo02.log', OPTIONS => DBMS_LOGMNR.ADDFILE);
EXEC DBMS_LOGMNR.ADD_LOGFILE(LOGFILENAME => '/opt/oracle/oradata/ORCLCDB/redo03.log', OPTIONS => DBMS_LOGMNR.ADDFILE);
EXEC DBMS_LOGMNR.START_LOGMNR(STARTSCN => 2554528, ENDSCN => 2554565, OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);
SELECT SCN, XID, XIDUSN, XIDSLT, XIDSQN, SQL_REDO, ROLLBACK FROM V$LOGMNR_CONTENTS WHERE TABLE_NAME = 'T1';
This gives:
SCN XID XIDUSN XIDSLT XIDSQN SQL_REDO ROLLBACK
__________ ___________________ _________ _________ _____________ _________________________________________________________________ ___________
2554545 D4001F00FFFFFFFF 212 31 4294967295 delete from "MY_USER"."T1" where ROWID = 'AAASkaAAHAAAAFcAAC'; 1
2554545 D4001F00FFFFFFFF 212 31 4294967295 delete from "MY_USER"."T1" where ROWID = 'AAASkaAAHAAAAFcAAB'; 1
So we can see that the actual XID should be `D4001F0014000000`. But if I narrow the SCN window for logMiner for just the ROLLBACK TO SAVEPOINT stmts, the last 8 digits of the XID will be padded with `FFFFFFFF`.
I'm wondering
- why this would happen?
- Is it possible to group sql_redo with the composite key of `(XIDUSN, XIDSLT)`, which seems to be consistent regardless of the scn window selection? In other words, if I found redo logs that share the same (XIDUSN, XIDSLT), can i say that they belong to the same transaction?
I don't know off hand, but if I had to offer a hypothesis.
For a transaction rollback, we would only need the undo segments and slot number. The wrap sequence is used when a slot is reused over time, but if I am doing a rollback, I know by definition that the seg/slot contains my undo information because there is no way that slot can be marked for reuse until I commit. For an active transaction, the seg/slot *must* be mine because no-one gets to overwrite it.
In terms of when your large scn range picks up the wrap sequence, I'd surmise that its just getting carried forward into the subsequent entries for the rollback.
(I stress - this is just hypothesis)