Logmnr獲取SQL長度超過4000的問題

yangtingkun發表於2011-10-02

如果LOGMNR獲取的SQL_REDOSQL_UNDO的長度超過4000,則會導致Oracle自動合併拆分行記錄。

 

 

一個簡單的例子來描述這個問題:

SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

Database altered.

SQL> SELECT GROUP# FROM V$LOG WHERE STATUS = 'CURRENT';

GROUP#
----------
         2

SQL> ALTER SYSTEM SWITCH LOGFILE;

System altered.

SQL> SELECT GROUP# FROM V$LOG WHERE STATUS = 'CURRENT';

GROUP#
----------
         3

SQL> CREATE TABLE T_LARGE_SQL (ID NUMBER, COL1 VARCHAR2(4000), COL2 VARCHAR2(4000), COL3 VARCHAR2(4000));

Table created.

SQL> INSERT INTO T_LARGE_SQL VALUES (1, 'A', 'A', 'A');

1 row created.

SQL> INSERT INTO T_LARGE_SQL VALUES (2, LPAD('B', 4000, 'B'), LPAD('B', 4000, 'B'), LPAD('B', 4000, 'B'));

1 row created.

SQL> COMMIT;

Commit complete.

SQL> SELECT MEMBER FROM V$LOGFILE WHERE GROUP# = 3;

MEMBER
----------------------------------------------------------------------------------------
/oracle/oradata/orcl/redo03.log

SQL> ALTER SYSTEM SWITCH LOGFILE;

System altered.

SQL> EXEC DBMS_LOGMNR.ADD_LOGFILE('/oracle/oradata/orcl/redo03.log', DBMS_LOGMNR.NEW)

PL/SQL procedure successfully completed.

SQL> EXEC DBMS_LOGMNR.START_LOGMNR(OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG)

PL/SQL procedure successfully completed.

SQL> CREATE TABLE T_BAK_LOGMNR AS SELECT * FROM V$LOGMNR_CONTENTS;

Table created.

SQL> COL SQL_REDO FORMAT A80 WRAP
SQL> SELECT RS_ID, SSN, CSF, SQL_REDO FROM T_BAK_LOGMNR WHERE SEG_NAME = 'T_LARGE_SQL';

RS_ID                                   SSN        CSF
-------------------------------- ---------- ----------
SQL_REDO
--------------------------------------------------------------------------------
 0x000069.0000001a.005c                   0          0
CREATE TABLE T_LARGE_SQL (ID NUMBER, COL1 VARCHAR2(4000), COL2 VARCHAR2(4000), C
OL3 VARCHAR2(4000));

 0x000069.0000002a.0010                   0          0
insert into "TEST"."T_LARGE_SQL"("ID","COL1","COL2","COL3") values ('1','A','A',
'A');

 0x000069.0000002a.01dc                   0          1
insert into "TEST"."T_LARGE_SQL"("ID","COL1","COL2","COL3") values ('2','BBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
.
.
.
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

 0x000069.0000002a.01dc                   0          1
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB','BBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
.
.
.
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

 0x000069.0000002a.01dc                   0          1
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB','B
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
.
.
.
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

 0x000069.0000002a.01dc                   0          0
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'
);

6 rows selected.

由於SQL_REDOSQL_UNDO都是VARCHAR2(4000)型別的欄位,當SQL本身很長導致長度超過4000時,必須透過多條記錄來儲存這一條語句。當發生這種情況時,除了SQL_REDOSQL_UNDO外,V$LOGMNR_CONTENTS檢視中透過RS_IDSSN來唯一標識一條語句。而CSF則標識當前是否是語句的結束部分。

比較有意思的是,Oracle並沒有給出一個順序列來標識同一個語句的多個行記錄之間的先後順序。雖然預設情況下,這個順序由Oracle自動保證,但是一旦使用者在查詢V$LOGMNR_CONTENTS檢視時新增了排序欄位,這時一個語句中的行記錄順序就可能無法保證,因此介於這種情況,對於查詢V$LOGMNR_CONTENTS檢視需要謹慎一些。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-708588/,如需轉載,請註明出處,否則將追究法律責任。

相關文章