在 Oracle 12c R2 中,LogMiner 是否支持 Table/Column 超过 30 个字符的名称?
In Oracle 12c R2 does LogMiner support Table/Column names longer than 30 characters?
到目前为止,任何列名超过 30 个字符的 table 在查询 V$LOGMNR_CONTENTS
时都会给出不支持的操作
如果我删除该列或将大小调整为 <=30,则所有 CRUD 操作都报告正常。
在 Oracle 12.2 中支持 128 个字符对象,所以我试图了解我是否配置有误。没完没了的谷歌搜索让我一无所获,Oracle 文档也没有。
提前致谢!
编辑
刚刚检查了 19c,同样的行为。兼容性设置为 19.0.0
编辑
有很多关于使用补充日志记录的评论,但无法创建与接受的答案相同的场景。
不管怎样,鉴于 Oracle 现在已经表示永远不会支持它,这无关紧要!
测试 I 运行 仍然无法正常工作
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
SELECT supplemental_log_data_min, supplemental_log_data_pk
FROM V$Database;
SUPPLEME SUP
-------- ---
YES NO
CREATE TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" (
"ID" NUMBER(10,0),
"NAME" VARCHAR2(254 BYTE)
);
ALTER TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" MODIFY ("ID" NOT NULL ENABLE);
ALTER TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" MODIFY ("NAME" NOT NULL ENABLE);
INSERT INTO atablewithquitealongnamelikeverylongactually VALUES (1, 'My Name');
DECLARE CURSOR LogMinerFileCursor IS
SELECT LogFile
FROM (
SELECT V$LOGFILE.Member AS LogFile,
FIRST_CHANGE# AS FirstSCN,
NEXT_CHANGE# AS LastSCN
FROM V$LOGFILE
INNER JOIN V$LOG ON V$LOGFILE.GROUP# = V$LOG.GROUP#
WHERE V$LOG.STATUS <> 'UNUSED'
AND FIRST_CHANGE# >= (SELECT RESETLOGS_CHANGE# FROM V$DATABASE)
UNION ALL
SELECT Name AS LogFile,
FIRST_CHANGE# AS FirstSCN,
NEXT_CHANGE# AS LastSCN
FROM V$ARCHIVED_LOG
WHERE FIRST_CHANGE# < (
SELECT MIN(FIRST_CHANGE#)
FROM V$LOGFILE
INNER JOIN V$LOG ON V$LOGFILE.GROUP# = V$LOG.GROUP#
WHERE V$LOG.STATUS <> 'UNUSED'
) AND FIRST_CHANGE# >= (SELECT RESETLOGS_CHANGE# FROM V$DATABASE)
) LogFiles WHERE FirstSCN >= 0 OR LastSCN > 0;
sDDL varchar2(2000);
BEGIN FOR LogMinerFileCursorRecords in LogMinerFileCursor LOOP
sDDL := 'BEGIN DBMS_LOGMNR.ADD_LOGFILE('''|| LogMinerFileCursorRecords.LogFile ||'''); END;';
DBMS_OUTPUT.Put_Line(sDDL);
execute immediate sDDL;
END LOOP;
COMMIT;
END;
BEGIN DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + + DBMS_LOGMNR.COMMITTED_DATA_ONLY ); END;
SELECT SQL_REDO AS RedoSQL
FROM V$LOGMNR_CONTENTS
WHERE SEG_OWNER = 'REPLICATION_OWNER'
AND TABLE_NAME = 'ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY'
REDOSQL
--------------------------------------------------------------------------------
CREATE TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY"
(
"ID" NUMBER(10,0),
"NAME" VARCHAR2(254 BYTE)
)
SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS
LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "REPLICATION_DATA";
REDOSQL
-------------------------------------------------------------------------------- ALTER TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" M ODIFY ("ID" NOT NULL ENABLE);
REDOSQL
-------------------------------------------------------------------------------- ALTER TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" M ODIFY ("NAME" NOT NULL ENABLE);
REDOSQL
-------------------------------------------------------------------------------- Unsupported
BEGIN DBMS_LOGMNR.END_LOGMNR; END;
新更新
几天后我确认这是一个错误。不幸的是,现在支持团队告诉我以下内容:
“这不是错误。从 12.2 开始,新 types/features 仅支持 dbms_rolling 和 golden gate。”结论是,LogMiner 将不支持名称超过 30 个字符的 table,即使 supplemental_logging 被禁用。他们将更新文档。只要我对此有更多详细信息,我就会更新答案。
SQL> select supplemental_log_data_min, supplemental_log_data_pk from v$database;
SUPPLEME SUP
-------- ---
YES YES
在这种情况下,当 table 的名称超过 30 个字符时,它将始终显示不支持任何 DML 操作。
SQL> select * from v$version ;
BANNER
--------------------------------------------------------------------------------
CON_ID
----------
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
0
PL/SQL Release 12.2.0.1.0 - Production
0
CORE 12.2.0.1.0 Production
0
BANNER
--------------------------------------------------------------------------------
CON_ID
----------
TNS for Linux: Version 12.2.0.1.0 - Production
0
NLSRTL Version 12.2.0.1.0 - Production
0
让我们开始测试用例
SQL> create table cpl_rep.my_table_with_a_very_long_name_with_more ( c1 number );
Table created.
SQL> insert into cpl_rep.my_table_with_a_very_long_name_with_more values ( 1 ) ;
1 row created.
SQL> insert into cpl_rep.my_table_with_a_very_long_name_with_more values ( 2 ) ;
1 row created
SQL> commit;
Commit complete.
SQL> select length(table_name) from dba_tables where table_name = upper('my_table_with_a_very_long_name_with_more');
LENGTH(TABLE_NAME)
------------------
40
SQL>
然后我开始我的 logminer 会话,首先我切换我的日志文件
SQL> alter system switch logfile ;
System altered.
SQL> exit
然后我再次输入以打开我的 logminer 会话
SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo11.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo21.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo12.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo22.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo13.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo23.ora' , 1);
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);
PL/SQL procedure successfully completed.
SQL> select count(*) from v$logmnr_contents where seg_name = upper('my_table_with_a_very_long_name_with_more');
COUNT(*)
----------
3
SQL> select operation,seg_name,sql_redo from v$logmnr_contents where seg_name = upper('my_table_with_a_very_long_name_with_more');
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
DDL
MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE
create table cpl_rep.my_table_with_a_very_long_name_with_more ( c1 number );
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
INSERT
MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE
insert into "CPL_REP"."MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE"("C1") values ('
1');
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
INSERT
MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE
insert into "CPL_REP"."MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE"("C1") values ('
2');
因此,如您所见,在我的例子中,当受影响的元素是 table.
时,不存在 30 个字符的限制。
让我们看看元素何时是列
SQL> create table cpl_rep.table_with_name_greater_than_30_characters ( column_greater_than_30_characters_test_case number );
Table created.
SQL> select length('table_with_name_greater_than_30_characters') , length('column_greater_than_30_characters_test_case') from dual ;
LENGTH('TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS')
----------------------------------------------------
LENGTH('COLUMN_GREATER_THAN_30_CHARACTERS_TEST_CASE')
-----------------------------------------------------
42
43
SQL> insert into cpl_rep.table_with_name_greater_than_30_characters values ( 1 );
1 row created.
SQL> r
1* insert into cpl_rep.table_with_name_greater_than_30_characters values ( 1 )
1 row created.
SQL> commit;
Commit complete.
SQL> insert into cpl_rep.table_with_name_greater_than_30_characters values ( 2 );
1 row created.
SQL> r
1* insert into cpl_rep.table_with_name_greater_than_30_characters values ( 2 )
1 row created.
SQL> commit;
Commit complete.
SQL> delete from cpl_rep.table_with_name_greater_than_30_characters where column_greater_than_30_characters_test_case=2 ;
2 rows deleted.
SQL> commit;
Commit complete.
$ sqlplus / as sysdba
SQL*Plus: Release 12.2.0.1.0 Production on Sun Jul 19 17:07:58 2020
Copyright (c) 1982, 2016, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo11.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo21.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo12.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo22.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo13.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo23.ora' , 1);
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);
PL/SQL procedure successfully completed.
SQL> select count(*) from v$logmnr_contents where seg_owner = 'CPL_REP' and seg_name = upper('table_with_name_greater_than_30_characters') ;
COUNT(*)
----------
3
SQL> select operation,seg_name,sql_redo from v$logmnr_contents where seg_owner = 'CPL_REP' and seg_name = upper('table_with_name_greater_than_30_characters') ;
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
DDL
TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS
create table cpl_rep.table_with_name_greater_than_30_characters ( column_greater
_than_30_characters_test_case number );
INSERT
TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
insert into "CPL_REP"."TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS"("COLUMN_GREAT
ER_THAN_30_CHARACTERS_TEST_CASE") values ('1');
INSERT
TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS
insert into "CPL_REP"."TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS"("COLUMN_GREAT
ER_THAN_30_CHARACTERS_TEST_CASE") values ('1');
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
因此,在我的例子中,我可以对两个列和大于 30 个字符的 tables 进行操作。
更新
在评论部分之后,我决定尝试使用 SUPPLEMENTAL_LOGGING 进行测试并且它有效。但是,当我为所有列 PK 添加 SUPPLEMENTAL_LOGGING 时,它不起作用
SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
Database altered.
SQL> select supplemental_log_data_min, supplemental_log_data_pk from v$database;
SUPPLEME SUP
-------- ---
YES NO
SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;
Database altered.
SQL> select supplemental_log_data_min, supplemental_log_data_pk from v$database;
SUPPLEME SUP
-------- ---
YES YES
SQL> create table cpl_rep.my_test_with_a_very_very_long_name_for_test ( c1 number ) ;
Table created.
SQL> insert into cpl_rep.my_test_with_a_very_very_long_name_for_test values ( 1 ) ;
1 row created.
SQL> insert into cpl_rep.my_test_with_a_very_very_long_name_for_test values ( 2 ) ;
1 row created.
SQL> commit ;
Commit complete.
SQL> insert into cpl_rep.my_test_with_a_very_very_long_name_for_test values ( 3 ) ;
1 row created.
SQL> commit;
Commit complete.
SQL> delete from cpl_rep.my_test_with_a_very_very_long_name_for_test where c1 = 3 ;
1 row deleted.
SQL>
切换日志文件并启动logminer。内容现在显示值 UNSUPPORTED。
SQL> select sql_redo , operation, seg_name from v$logmnr_contents where seg_name = upper('my_test_with_a_very_very_long_name_for_test') ;
SQL_REDO
--------------------------------------------------------------------------------
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
create table cpl_rep.my_test_with_a_very_very_long_name_for_test ( c1 number ) ;
DDL
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
Unsupported
UNSUPPORTED
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
SQL_REDO
--------------------------------------------------------------------------------
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
Unsupported
UNSUPPORTED
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
Unsupported
UNSUPPORTED
SQL_REDO
--------------------------------------------------------------------------------
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
Unsupported
UNSUPPORTED
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
SQL>
关键是SUPPLEMENTAL_LOGGINGPK,而且只影响DML操作,因为DDL显示的是真正执行的命令。
最后 Oracle 针对此问题打开了一个错误:Log Miner 显示 SQL_REDO 不支持 table 名称超过 30 个字符(文档 ID 2703406.1)。
虽然还没有解决:(
只是为了结束这个循环。 Oracle 21c 中的文档已更新以指定限制。
真的不喜欢 Oracle 如何处理他们的文档,但是嘿,至少它在那里。
到目前为止,任何列名超过 30 个字符的 table 在查询 V$LOGMNR_CONTENTS
时都会给出不支持的操作如果我删除该列或将大小调整为 <=30,则所有 CRUD 操作都报告正常。
在 Oracle 12.2 中支持 128 个字符对象,所以我试图了解我是否配置有误。没完没了的谷歌搜索让我一无所获,Oracle 文档也没有。
提前致谢!
编辑
刚刚检查了 19c,同样的行为。兼容性设置为 19.0.0
编辑
有很多关于使用补充日志记录的评论,但无法创建与接受的答案相同的场景。
不管怎样,鉴于 Oracle 现在已经表示永远不会支持它,这无关紧要!
测试 I 运行 仍然无法正常工作
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
SELECT supplemental_log_data_min, supplemental_log_data_pk
FROM V$Database;
SUPPLEME SUP
-------- ---
YES NO
CREATE TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" (
"ID" NUMBER(10,0),
"NAME" VARCHAR2(254 BYTE)
);
ALTER TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" MODIFY ("ID" NOT NULL ENABLE);
ALTER TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" MODIFY ("NAME" NOT NULL ENABLE);
INSERT INTO atablewithquitealongnamelikeverylongactually VALUES (1, 'My Name');
DECLARE CURSOR LogMinerFileCursor IS
SELECT LogFile
FROM (
SELECT V$LOGFILE.Member AS LogFile,
FIRST_CHANGE# AS FirstSCN,
NEXT_CHANGE# AS LastSCN
FROM V$LOGFILE
INNER JOIN V$LOG ON V$LOGFILE.GROUP# = V$LOG.GROUP#
WHERE V$LOG.STATUS <> 'UNUSED'
AND FIRST_CHANGE# >= (SELECT RESETLOGS_CHANGE# FROM V$DATABASE)
UNION ALL
SELECT Name AS LogFile,
FIRST_CHANGE# AS FirstSCN,
NEXT_CHANGE# AS LastSCN
FROM V$ARCHIVED_LOG
WHERE FIRST_CHANGE# < (
SELECT MIN(FIRST_CHANGE#)
FROM V$LOGFILE
INNER JOIN V$LOG ON V$LOGFILE.GROUP# = V$LOG.GROUP#
WHERE V$LOG.STATUS <> 'UNUSED'
) AND FIRST_CHANGE# >= (SELECT RESETLOGS_CHANGE# FROM V$DATABASE)
) LogFiles WHERE FirstSCN >= 0 OR LastSCN > 0;
sDDL varchar2(2000);
BEGIN FOR LogMinerFileCursorRecords in LogMinerFileCursor LOOP
sDDL := 'BEGIN DBMS_LOGMNR.ADD_LOGFILE('''|| LogMinerFileCursorRecords.LogFile ||'''); END;';
DBMS_OUTPUT.Put_Line(sDDL);
execute immediate sDDL;
END LOOP;
COMMIT;
END;
BEGIN DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + + DBMS_LOGMNR.COMMITTED_DATA_ONLY ); END;
SELECT SQL_REDO AS RedoSQL
FROM V$LOGMNR_CONTENTS
WHERE SEG_OWNER = 'REPLICATION_OWNER'
AND TABLE_NAME = 'ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY'
REDOSQL
--------------------------------------------------------------------------------
CREATE TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY"
(
"ID" NUMBER(10,0),
"NAME" VARCHAR2(254 BYTE)
)
SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS
LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "REPLICATION_DATA";
REDOSQL
-------------------------------------------------------------------------------- ALTER TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" M ODIFY ("ID" NOT NULL ENABLE);
REDOSQL
-------------------------------------------------------------------------------- ALTER TABLE "REPLICATION_OWNER"."ATABLEWITHQUITEALONGNAMELIKEVERYLONGACTUALLY" M ODIFY ("NAME" NOT NULL ENABLE);
REDOSQL
-------------------------------------------------------------------------------- Unsupported
BEGIN DBMS_LOGMNR.END_LOGMNR; END;
新更新
几天后我确认这是一个错误。不幸的是,现在支持团队告诉我以下内容:
“这不是错误。从 12.2 开始,新 types/features 仅支持 dbms_rolling 和 golden gate。”结论是,LogMiner 将不支持名称超过 30 个字符的 table,即使 supplemental_logging 被禁用。他们将更新文档。只要我对此有更多详细信息,我就会更新答案。
SQL> select supplemental_log_data_min, supplemental_log_data_pk from v$database;
SUPPLEME SUP
-------- ---
YES YES
在这种情况下,当 table 的名称超过 30 个字符时,它将始终显示不支持任何 DML 操作。
SQL> select * from v$version ;
BANNER
--------------------------------------------------------------------------------
CON_ID
----------
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
0
PL/SQL Release 12.2.0.1.0 - Production
0
CORE 12.2.0.1.0 Production
0
BANNER
--------------------------------------------------------------------------------
CON_ID
----------
TNS for Linux: Version 12.2.0.1.0 - Production
0
NLSRTL Version 12.2.0.1.0 - Production
0
让我们开始测试用例
SQL> create table cpl_rep.my_table_with_a_very_long_name_with_more ( c1 number );
Table created.
SQL> insert into cpl_rep.my_table_with_a_very_long_name_with_more values ( 1 ) ;
1 row created.
SQL> insert into cpl_rep.my_table_with_a_very_long_name_with_more values ( 2 ) ;
1 row created
SQL> commit;
Commit complete.
SQL> select length(table_name) from dba_tables where table_name = upper('my_table_with_a_very_long_name_with_more');
LENGTH(TABLE_NAME)
------------------
40
SQL>
然后我开始我的 logminer 会话,首先我切换我的日志文件
SQL> alter system switch logfile ;
System altered.
SQL> exit
然后我再次输入以打开我的 logminer 会话
SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo11.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo21.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo12.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo22.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo13.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo23.ora' , 1);
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);
PL/SQL procedure successfully completed.
SQL> select count(*) from v$logmnr_contents where seg_name = upper('my_table_with_a_very_long_name_with_more');
COUNT(*)
----------
3
SQL> select operation,seg_name,sql_redo from v$logmnr_contents where seg_name = upper('my_table_with_a_very_long_name_with_more');
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
DDL
MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE
create table cpl_rep.my_table_with_a_very_long_name_with_more ( c1 number );
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
INSERT
MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE
insert into "CPL_REP"."MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE"("C1") values ('
1');
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
INSERT
MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE
insert into "CPL_REP"."MY_TABLE_WITH_A_VERY_LONG_NAME_WITH_MORE"("C1") values ('
2');
因此,如您所见,在我的例子中,当受影响的元素是 table.
时,不存在 30 个字符的限制。让我们看看元素何时是列
SQL> create table cpl_rep.table_with_name_greater_than_30_characters ( column_greater_than_30_characters_test_case number );
Table created.
SQL> select length('table_with_name_greater_than_30_characters') , length('column_greater_than_30_characters_test_case') from dual ;
LENGTH('TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS')
----------------------------------------------------
LENGTH('COLUMN_GREATER_THAN_30_CHARACTERS_TEST_CASE')
-----------------------------------------------------
42
43
SQL> insert into cpl_rep.table_with_name_greater_than_30_characters values ( 1 );
1 row created.
SQL> r
1* insert into cpl_rep.table_with_name_greater_than_30_characters values ( 1 )
1 row created.
SQL> commit;
Commit complete.
SQL> insert into cpl_rep.table_with_name_greater_than_30_characters values ( 2 );
1 row created.
SQL> r
1* insert into cpl_rep.table_with_name_greater_than_30_characters values ( 2 )
1 row created.
SQL> commit;
Commit complete.
SQL> delete from cpl_rep.table_with_name_greater_than_30_characters where column_greater_than_30_characters_test_case=2 ;
2 rows deleted.
SQL> commit;
Commit complete.
$ sqlplus / as sysdba
SQL*Plus: Release 12.2.0.1.0 Production on Sun Jul 19 17:07:58 2020
Copyright (c) 1982, 2016, Oracle. All rights reserved.
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo11.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo21.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo12.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo22.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo1/redo13.ora' , 1);
exec dbms_logmnr.add_logfile('/bbdd_odcgrc1r/redo2/redo23.ora' , 1);
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
PL/SQL procedure successfully completed.
SQL>
SQL> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);
PL/SQL procedure successfully completed.
SQL> select count(*) from v$logmnr_contents where seg_owner = 'CPL_REP' and seg_name = upper('table_with_name_greater_than_30_characters') ;
COUNT(*)
----------
3
SQL> select operation,seg_name,sql_redo from v$logmnr_contents where seg_owner = 'CPL_REP' and seg_name = upper('table_with_name_greater_than_30_characters') ;
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
DDL
TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS
create table cpl_rep.table_with_name_greater_than_30_characters ( column_greater
_than_30_characters_test_case number );
INSERT
TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
insert into "CPL_REP"."TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS"("COLUMN_GREAT
ER_THAN_30_CHARACTERS_TEST_CASE") values ('1');
INSERT
TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS
insert into "CPL_REP"."TABLE_WITH_NAME_GREATER_THAN_30_CHARACTERS"("COLUMN_GREAT
ER_THAN_30_CHARACTERS_TEST_CASE") values ('1');
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
SQL_REDO
--------------------------------------------------------------------------------
因此,在我的例子中,我可以对两个列和大于 30 个字符的 tables 进行操作。
更新
在评论部分之后,我决定尝试使用 SUPPLEMENTAL_LOGGING 进行测试并且它有效。但是,当我为所有列 PK 添加 SUPPLEMENTAL_LOGGING 时,它不起作用
SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
Database altered.
SQL> select supplemental_log_data_min, supplemental_log_data_pk from v$database;
SUPPLEME SUP
-------- ---
YES NO
SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;
Database altered.
SQL> select supplemental_log_data_min, supplemental_log_data_pk from v$database;
SUPPLEME SUP
-------- ---
YES YES
SQL> create table cpl_rep.my_test_with_a_very_very_long_name_for_test ( c1 number ) ;
Table created.
SQL> insert into cpl_rep.my_test_with_a_very_very_long_name_for_test values ( 1 ) ;
1 row created.
SQL> insert into cpl_rep.my_test_with_a_very_very_long_name_for_test values ( 2 ) ;
1 row created.
SQL> commit ;
Commit complete.
SQL> insert into cpl_rep.my_test_with_a_very_very_long_name_for_test values ( 3 ) ;
1 row created.
SQL> commit;
Commit complete.
SQL> delete from cpl_rep.my_test_with_a_very_very_long_name_for_test where c1 = 3 ;
1 row deleted.
SQL>
切换日志文件并启动logminer。内容现在显示值 UNSUPPORTED。
SQL> select sql_redo , operation, seg_name from v$logmnr_contents where seg_name = upper('my_test_with_a_very_very_long_name_for_test') ;
SQL_REDO
--------------------------------------------------------------------------------
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
create table cpl_rep.my_test_with_a_very_very_long_name_for_test ( c1 number ) ;
DDL
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
Unsupported
UNSUPPORTED
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
SQL_REDO
--------------------------------------------------------------------------------
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
Unsupported
UNSUPPORTED
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
Unsupported
UNSUPPORTED
SQL_REDO
--------------------------------------------------------------------------------
OPERATION
--------------------------------
SEG_NAME
--------------------------------------------------------------------------------
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
Unsupported
UNSUPPORTED
MY_TEST_WITH_A_VERY_VERY_LONG_NAME_FOR_TEST
SQL>
关键是SUPPLEMENTAL_LOGGINGPK,而且只影响DML操作,因为DDL显示的是真正执行的命令。
最后 Oracle 针对此问题打开了一个错误:Log Miner 显示 SQL_REDO 不支持 table 名称超过 30 个字符(文档 ID 2703406.1)。
虽然还没有解决:(
只是为了结束这个循环。 Oracle 21c 中的文档已更新以指定限制。
真的不喜欢 Oracle 如何处理他们的文档,但是嘿,至少它在那里。