【问题标题】:In Oracle 12c R2 does LogMiner support Table/Column names longer than 30 characters?在 Oracle 12c R2 中,LogMiner 是否支持超过 30 个字符的表/列名称?
【发布时间】:2020-07-21 01:55:16
【问题描述】:

到目前为止,任何列名超过 30 个字符的表在查询 V$LOGMNR_CONTENTS 时都会给出 UNSUPPORTED 操作

如果我删除列或将大小调整为

在 Oracle 12.2 中支持 128 个字符对象,所以我试图了解我是否配置了错误。无休止的谷歌搜索让我无处可去,Oracle 文档也没有。

提前致谢!

编辑

刚刚检查了 19c,同样的行为。兼容性设置为 19.0.0

编辑

关于使用补充日志记录的许多 cmets,但无法创建与接受的答案相同的场景。

不管怎样,鉴于 Oracle 现在已经表示永远不会支持它,这无关紧要!

测试我在仍然无法工作的地方运行

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 实例上看到了同样的问题。我愤世嫉俗的一面说,这个问题永远不会有解决方案,因为甲骨文似乎试图杀死 LogMiner 并强迫人们购买 GoldenGate。但希望我错了,有办法让它发挥作用。
  • 我认为,问题在于Long Identifier。根据OraDocs:The maximum length of identifier names depends on the value of the COMPATIBLE initialization parameter. 。因此,设置兼容 12.2 应该可以解决问题。
  • 设置为 12.2,所以不是这样。
  • 刚刚检查了 19c,同样的行为。兼容性设置为 19.0.0
  • @JonHeller 相信我,即使在 19c 他们也在推动客户选择 GoldenGate。

标签: oracle oracle12c logminer


【解决方案1】:

只是为了结束这个循环。 Oracle 21c 中的文档已更新以指定限制。

https://docs.oracle.com/en/database/oracle/oracle-database/21/sutil/oracle-logminer-utility.html#GUID-7594F0D7-0ACD-46E6-BD61-2751136ECDB4

真的不喜欢 Oracle 如何处理他们的文档,但是嘿,至少它在那里。

【讨论】:

    【解决方案2】:

    Oracle 终于针对这个问题打开了一个错误:Log Miner Shows SQL_REDO As UNSUPPORTED for table names longed 30 characters (Doc ID 2703406.1)。

    虽然还没有解决方案:(

    【讨论】:

      【解决方案3】:

      新更新

      几天后我确认这是一个错误。不幸的是,现在支持团队告诉我以下内容:

      “这不是错误。从 12.2 开始,仅 dbms_rolling 和金门支持新类型/功能。”结论,LogMiner 不支持名称超过 30 个字符的表,即使supplemental_logging 被禁用。他们将更新文档。只要我对此有更多详细信息,我就会更新答案。

      SQL> select supplemental_log_data_min, supplemental_log_data_pk from v$database;
      
      SUPPLEME SUP
      -------- ---
      YES YES
      

      在这种情况下,当表的名称超过 30 个字符时,任何 DML 操作都将始终显示 UNSUPPORTED。

      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');
      

      因此,如您所见,在我的例子中,当受影响的元素是表格时,没有 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 个字符的列和表进行操作。

      更新

      在完成 cmets 部分之后,我决定尝试使用 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_LOGGING PK,而且它只影响 DML 操作,因为 DDL 显示了实际执行的命令。

      【讨论】:

      • 我可以看到的唯一设置差异可能是 Linux 与 Windows。猜测您的 Oracle 安装在 Linux 发行版上?
      • @BrandonBillingham,确实我的 12c 和 19c 分别在 Linux Red Hat 7 和 Oracle LInux 上。我很好奇我运行两个测试用例的问题,但我找不到名称长度有任何问题。
      • 我运行了与您完全相同的代码、相同的表/列值等,唯一的区别是操作系统,我在 SQL_REDO 列中得到了 UNSUPPORTED。
      • 我会就此向支持人员询问,并让您知道他们的回答:)
      • @BrandonBillingham,我刚收到支持部门的回复,他们说 Windows 也同样支持。如果您有支持,您应该打开 SR 并上传警报日志和补丁清单,也许您有需要解决的错误
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 1970-01-01
      • 2014-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多