В Oracle 12c R2 поддерживает ли LogMiner имена таблиц / столбцов длиной более 30 символов?
Пока что любая таблица, в которой имя столбца превышает 30 символов, дает НЕПОДДЕРЖИВАЕМУЮ операцию при запросе V$LOGMNR_CONTENTS.
Если я отброшу столбец или отрегулирую размер до <=30, то все операции CRUD будут отмечены нормально.
В Oracle 12.2 поддерживаются 128 символьных объектов, поэтому я пытаюсь понять, не настроил ли я что-то неправильно. Бесконечный поиск в Google ни к чему не привел, как и документация Oracle.
Заранее спасибо!
редактировать
Только что проверил 19c, поведение такое же. Установлена совместимость 19.0.0
РЕДАКТИРОВАТЬ
Было много комментариев относительно использования дополнительного журнала, но не могу создать тот же сценарий, что и принятый ответ.
В любом случае, учитывая, что 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;
3 ответа
НОВОЕ ОБНОВЛЕНИЕ
Через несколько дней я подтвердил, что это ошибка. К сожалению, сейчас служба поддержки сообщает мне следующее:
"Это не ошибка. С версии 12.2 новые типы / функции поддерживаются только для dbms_rolling и Golden Gate". Заключение, таблицы с именами более 30 символов не будут поддерживаться в LogMiner, даже если additional_logging отключено. Они собираются обновить документацию. Я буду обновлять ответ, если у меня будет более подробная информация по этому поводу.
SQL> select supplemental_log_data_min, supplemental_log_data_pk from v$database;
SUPPLEME SUP
-------- ---
YES YES
В этом случае он всегда будет показывать UNSUPPORTED для любой операции DML, если имя таблицы содержит более 30 символов.
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 символов.
ОБНОВИТЬ
После разделов комментариев я решил попробовать тест с SUPPLEMENTAL_LOGGING, и он работает. Однако, когда я добавляю SUPPLEMENTAL_LOGGING для всех столбцов PK, он не работает.
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 показывает реальную выполненную команду.
Наконец, Oracle открыла ошибку для этой проблемы: Log Miner показывает SQL_REDO как UNSUPPORTED для имен таблиц длиннее 30 символов (идентификатор документа 2703406.1).
Но пока нет разрешения :(
Просто, чтобы закрыть петлю на этом. Документация была обновлена в Oracle 21c, чтобы указать ограничение.
На самом деле не нравится, как Oracle делает свою документацию, но, по крайней мере, она есть.