Oracle Logminer中的invalid row_id “AAAAAAAAAAAAAAAAAA”
最近有个客户在做迁移oracle到Oceanbase时,使用的是原厂的OMS数据迁移同步工具,在迁移或数据同步完数据库发现数据存在差异, 应该是一种基于logminer的log stream形式,发现一张表含有Lob字段在logminer的视图中对应的rowid只有update,没有insert, 经过事务xid的查找发现insert所对应的是ROW_ID为”AAAAAAAAAAAAAAAAAA”,显然这是一个无效的rowid, 如果是基于rowid那同步数据就可能丢失了。我发现oracle11g和23c这方面还有点差异,简单记录。
环境11.2.0.4
create table anbob.TEST_LOG ( id number , fullname varchar2(50) , age number , description clob ); CREATE TABLE anbob.TEST ( ID INTEGER, COL1 VARCHAR2(4000), COL2 INTEGER ); select dbms_flashback.get_system_change_number from dual; insert into anbob.TEST_LOG(id,fullname,age) values(1,'anbob builder',35); update anbob.TEST_LOG set description=to_clob('anbob.com') where id=1; INSERT INTO anbob.TEST_LOG(id,fullname,age,description) values(2,'anbob builder',35, DBMS_RANDOM.STRING('U', 10)); commit; INSERT INTO anbob.TEST (ID, COL1, COL2) VALUES (0, 'TEXT', 1); commit; select dbms_flashback.get_system_change_number from dual; exec DBMS_LOGMNR.ADD_LOGFILE('+DATA/rac11g/onlinelog/group_2.261.1164470467', DBMS_LOGMNR.NEW); EXECUTE DBMS_LOGMNR.START_LOGMNR(STARTSCN=>24334811738, ENDSCN=>24334811859, - OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + - DBMS_LOGMNR.COMMITTED_DATA_ONLY + DBMS_LOGMNR.NO_ROWID_IN_STMT + DBMS_LOGMNR.NO_SQL_DELIMITER);
Note:
创建了一个包含lob的表test_lob和一个不含LOB的test表做为对比。
查看操作日志
SQL> r 1 SELECT 2 scn,start_scn,timestamp,xid,operation,table_name, row_id,sql_redo 3 FROM V$LOGMNR_CONTENTS 4 where SEG_OWNER='ANBOB' OR XID in('BD0B0400E0210000','C10B180009220000') 5* ORDER BY 1 asc SCN START_SCN TIMESTAMP XID OPERATION TABLE_NAME ROW_ID SQL_REDO --------------- --------------- ------------------- ---------------- --------------- --------------- ------------------------------------ ---------------------------------------------------------------------- 24334811772 24334811772 2024-11-22 16:52:21 C10B180009220000 START AAAAAAAAAAAAAAAAAA set transaction read write 24334811772 24334811772 2024-11-22 16:52:21 C10B180009220000 INSERT TEST_LOG AAAAAAAAAAAAAAAAAA insert into "ANBOB"."TEST_LOG"("ID","FULLNAME","AGE","DESCRIPTION") v alues ('1','anbob builder','35',EMPTY_CLOB()) 24334811774 24334811772 2024-11-22 16:52:21 C10B180009220000 UPDATE TEST_LOG AAAd5rAAEAAEXYdAAA update "ANBOB"."TEST_LOG" set "DESCRIPTION" = NULL where "ID" = '1' a nd "FULLNAME" = 'anbob builder' and "AGE" = '35' 24334811781 24334811772 2024-11-22 16:52:27 C10B180009220000 UPDATE TEST_LOG AAAAAAAAAAAAAAAAAA update "ANBOB"."TEST_LOG" set "DESCRIPTION" = EMPTY_CLOB() where "ID" = '1' and "FULLNAME" = 'anbob builder' and "AGE" = '35' 24334811782 24334811772 2024-11-22 16:52:27 C10B180009220000 UPDATE TEST_LOG AAAd5rAAEAAEXYdAAA update "ANBOB"."TEST_LOG" set "DESCRIPTION" = 'anbob.com' where "ID" = '1' and "FULLNAME" = 'anbob builder' and "AGE" = '35' 24334811814 24334811772 2024-11-22 16:52:53 C10B180009220000 INSERT TEST_LOG AAAAAAAAAAAAAAAAAA insert into "ANBOB"."TEST_LOG"("ID","FULLNAME","AGE","DESCRIPTION") v alues ('2','anbob builder','35',EMPTY_CLOB()) 24334811814 24334811772 2024-11-22 16:52:53 C10B180009220000 UPDATE TEST_LOG AAAd5rAAEAAEXYdAAB update "ANBOB"."TEST_LOG" set "DESCRIPTION" = 'BESVGEYSJO' where "ID" = '2' and "FULLNAME" = 'anbob builder' and "AGE" = '35' 24334811820 24334811772 2024-11-22 16:52:59 C10B180009220000 COMMIT AAAAAAAAAAAAAAAAAA commit 24334811847 24334811847 2024-11-22 16:53:08 BD0B0400E0210000 START AAAd5uAAAAAAAAAAAA set transaction read write 24334811847 24334811847 2024-11-22 16:53:08 BD0B0400E0210000 INSERT TEST AAAd5uAAEAAEXY9AAA insert into "ANBOB"."TEST"("ID","COL1","COL2") values ('0','TEXT','1') 24334811851 24334811847 2024-11-22 16:53:11 BD0B0400E0210000 COMMIT AAAAAAAAAAAAAAAAAA commit 11 rows selected.
Note:
1,对于事务操作start,commit,rollback 对应的rowid 都是AAAAAAAAAAAAAAAAAA
2, 对于lob列的insert 不带lob col分自动分为2条,先insert lobcol= EMPTY_CLOB(), 再update lobcol=null, 第1个insert row_id=AAAAAAAAAAAAAAAAAA
3, 对于lob列的update同样分为2条, 先update lobcol= EMPTY_CLOB(), 再update lobcol=具体值, 第1个update row_idAAAAAAAAAAAAAAAAAA
4,对于clob列的insert 带lob col分自动分为2条,先insert lobcol= EMPTY_CLOB(), 再update lobcol=null,第1个insert row_id=AAAAAAAAAAAAAAAAAA
5, 并不是所有insert 对应的rowid都是AAAAAAAAAAAAAAAAAA, 对于不含lob的表 insert row_id为实际rowid.
Oralce 23c 测试
create table anbob.testtable ( id number , fullname varchar2(50) , age number , description clob ); Table created. SQL> select dbms_flashback.get_system_change_number from dual; GET_SYSTEM_CHANGE_NUMBER ------------------------ 820499821 SQL> insert into anbob.testtable(id,fullname,age) values(1,'anbob builder',35); 1 row created. SQL> update anbob.testtable set description=to_clob('anbob.com') where id=1; 1 row updated. SQL> commit; Commit complete. SQL> select dbms_flashback.get_system_change_number from dual; GET_SYSTEM_CHANGE_NUMBER ------------------------ 820500013 SQL>EXECUTE DBMS_LOGMNR.START_LOGMNR(STARTSCN=>820499821, ENDSCN=>820500013, - OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + - DBMS_LOGMNR.COMMITTED_DATA_ONLY + DBMS_LOGMNR.NO_ROWID_IN_STMT + DBMS_LOGMNR.NO_SQL_DELIMITER); PL/SQL procedure successfully completed.
NOTE:
1, 23c不支持ORA-44609: CONTINOUS_MINE is desupported for use with DBMS_LOGMNR.START_LOGMNR.
2, 23c这里并没有做DBMS_LOGMNR.ADD_LOGFILE,看来已经可以自动查找
查看23c的logminer日志
SELECT scn,start_scn,timestamp,xid,operation,table_name, row_id,sql_redo FROM V$LOGMNR_CONTENTS where SEG_OWNER='ANBOB' OR XID='0A0020004CC60200' ORDER BY xid asc,sequence# asc / SCN START_SCN TIMESTAMP XID OPERATION TABLE_NAME ROW_ID SQL_REDO ---------- ---------- ------------------- ---------------- -------------------------------- ------------------------------ ------------------ ---------------------------------------- 820499858 820499858 2024-11-23 00:18:37 0A0020004CC60200 START AAAsPAAAAAAAAAAAAA set transaction read write 820499858 820499858 2024-11-23 00:18:37 0A0020004CC60200 INSERT TESTTABLE AAAsPAAAdAAAKc8AAA insert into "ANBOB"."TESTTABLE"("ID","FU LLNAME","AGE","DESCRIPTION") values ('1' ,'anbob builder','35',NULL) 820499988 820499858 2024-11-23 00:19:04 0A0020004CC60200 UPDATE TESTTABLE AAAsPAAAdAAAKc8AAA update "ANBOB"."TESTTABLE" set "DESCRIPT ION" = 'anbob.com' where 820500008 820499858 2024-11-23 00:19:12 0A0020004CC60200 COMMIT AAAAAAAAAAAAAAAAAA commit
Note:
在23c中默认对于含有lob的列表DML并没有拆分为2条,没有先EMPTY_CLOB()。
注意: 对于基于日志的数据同步,还是要研究数据库不同版本的日志内容变化,这里11g和23c的不同还隐藏一个11g使用的是basefile,而23c是SECUREFILE, 和存储属性是否有没有关系?12c和19c又是什么样?时间关系请自行测试。
还有更多异构数据迁移问题隐藏在项目中,如果您有国产化改造咨询需求,可以考虑联系我们(www.anbob.com首页的联系方式)
目前这篇文章还没有评论(Rss)