原 关于v$logmnr_contents视图的SQL_REDO列只有rowid信息没有附加日志信息,且SQL_UNDO为空的排查
Tags: Oracle原创LogMinerv$logmnr_contents
现象
好久没研究Oracle了,今天碰到一个LogMiner的问题,特此记录一下。
数据库架构为:
此架构很简单,一个Oracle主库(简称A库),一个物理备库(简称B库),一个可读可写的Oracle库(简称C库),B和C在同一台机器上,这样的话,C库就可以通过LogMiner+平面文件字典的形式实时的解析B库的在线和归档日志,最后将解析出来的SQL通过简单转换,可以应用的其他的PG、MySQL、SQL Server等库。
开发反馈过来说,从B库解析出来的SQL包含如下的形式,delete from "SYS"."AABB" where ROWID = 'AAAXCBAAEAAAAIOAAA';,这类SQL不能转换为真实执行的SQL语句,可能会导致数据不一致的问题。
排查过程
我起初以为是解析过程有问题,然后自己在出问题的数据库中捕捉了一下,发现的确有这种情况,一时之间有点蒙了。因为对于delete和insert语句来说,redo日志肯定会记录完整的字段内容,所以,这个肯定和附加日志是没有关系的。
接下来就是,在自己的环境中做了很多实验,发现不会只包含一个ROWID,都是这种情况:delete from "SYS"."AABB" where "ID" = '3' and ROWID = 'AAAUU4AABAAAc4DAAF';,且SQL_UNDO列都是有值的,而出现问题的删除语句的SQL_UNDO列是空的,这就比较奇怪咯。
最后只能搜索mos了,搜“v$logmnr_contents sql_redo only rowid”,结果发现第1篇就是Rollback Statement Does Not Contain Supplemental Log Data (Doc ID 462948.1),里边提到了,若执行了ROLLBACK,则会出现这种情况。于是我立马验证,发现的确如此。
那返回去想一下,为啥在生产环境验证的时候,一直有问题,而自己的环境却没有问题呢,因为:生产环境的SQL是客户这边给的,我没有细看,而我自己的环境的SQL是我之前整理过的SQL,因为SQL不能复制,故出现了这个问题。具体差异在哪里呢,在于我自己的SQL在解析的时候加了一个选项:options=>dbms_logmnr.committed_data_only ,这个表示只解析已提交的数据,问题就出现在这。
所以,排查完的结论就是,这种SQL不影响数据的完整的性,因为是主库回滚掉的,而解析库不能解析,那么也不会应用到其他库中。
完毕!
实验示例SQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | DROP TABLE AABB; create table AABB(id int); insert into "SYS"."AABB"("ID") values ('1'); commit; begin insert into "SYS"."AABB"("ID") values ('3'); rollback; end; SELECT ' dbms_logmnr.add_logfile(''' || MEMBER || ''');' FROM v$logfile; select * from v$archived_log WHERE sequence#>=678; select * from v$archived_log where to_date('2025-03-14 14:49:36','YYYY-MM-DD HH24:MI:SS') between first_time and next_time and dest_id=1 order by thread#; BEGIN dbms_logmnr.add_logfile('/tmp/o1_mf_1_680_mx7yt0hj_.arc'); dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog); -- dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog + dbms_logmnr.committed_data_only); -- dbms_logmnr.start_logmnr(dictfilename=>'/home/oracle/log.ora'); END; SELECT scn, sql_redo, a.SQL_UNDO,timestamp,session_info,session#,serial#,ssn,rollback FROM v$logmnr_contents a WHERE a.TABLE_NAME = upper('AABB') -- and a.operation='DELETE' -- and a.ROW_ID = 'AAAYaiABfAABlvOAAc' and timestamp>= to_date('2025-03-14 10:20:00','YYYY-MM-DD HH24:MI:SS') and rownum<=10 order by scn,SSN; begin dbms_logmnr.end_logmnr(); end; |
结果:
Rollback Statement Does Not Contain Supplemental Log Data (Doc ID 462948.1)文档
You use LogMiner to grab the information from Redo logs in source database (SUPPLEMENTAL LOGGING enabled for PK and UI) and apply this to target database. The view V$LOGMNR_CONTENTS doesn't show the complete syntax for SQL_REDO of the 'ROLLBACK' statements (including PK/UI, only ROWID is available, what is not applicable at target database).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | connect / as sysdba alter database add supplemental log data (all) columns; connect test/test drop table tab001; purge recyclebin; create table tab001 (col001 number); alter table tab001 add constraint tab001_pk primary key (col001); alter table tab001 add supplemental log data (primary key) columns; alter table tab001 add supplemental log data (unique) columns; insert into tab001 values (1); rollback; |




