1 說明
In some cases, you might want to undo an online redefinition of a table. For example, the performance of operations on the table might be worse after the redefinition than it was before the redefinition. In these cases, you can roll back the table to its original definition while preserving all of the DML changes made to the table after it was redefined. Online table redefinition rollback is used mainly when redefinition changes the storage characteristics of the table, and the changes unexpectedly result in degraded performance.
在12.2中,在線上表重新定義之後,您可以在線上表重新定義之前将表滾回它的定義,同時保留對表的所有資料操作語言(DML)更改。通過DBMS_REDEFINITION包來實作。
可以快速復原掉表結構的修改操作,而且不會影響之前已經對表做的DML操作(增删改查)。
2 測試
2.1 建立測試表-修改之前的表結構
CREATE TABLESPACE cndba
DATAFILE 'cndba01.dbf' SIZE 10M
ONLINE;
CREATE TABLE lei.test_rollback
(id NUMBER(6) PRIMARY KEY,
name VARCHAR2(20))
TABLESPACE cndba
STORAGE (INITIAL 2M);
2.2 驗證該表是線上重新的
BEGIN
DBMS_REDEFINITION.CAN_REDEF_TABLE(
uname => 'lei',
tname =>'test_rollback', --源表
options_flag => DBMS_REDEFINITION.CONS_USE_PK);
END;
/
2.3 建立臨時表
臨時表用來儲存修改表結構期間所有執行DML操作。
#建立一個壓縮表空間來存放臨時表
CREATE TABLESPACE tst_cmp_rollback_tbs
DEFAULT ROW STORE COMPRESS ADVANCED
DATAFILE 'tst_cmp_rollback_tbs.dbf' SIZE 10M
ONLINE;
#建立臨時表
CREATE TABLE lei.int_tst_rollback
(id NUMBER(6) PRIMARY KEY,
name VARCHAR2(20))
TABLESPACE tst_cmp_rollback_tbs
STORAGE (INITIAL 2M);
注意:表的字段名保持一緻。
2.4 啟動redefinition程序
SQL> BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE(
uname => 'lei',
orig_table => 'test_rollback',
int_table => 'int_tst_rollback',
options_flag => DBMS_REDEFINITION.CONS_USE_PK,
enable_rollback => TRUE); --一定是TRUE
END;
/
PL/SQL procedure successfully completed.
2.5 拷貝依賴對象
DECLARE
num_errors PLS_INTEGER;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(
uname => 'lei',
orig_table => 'test_rollback',
int_table => 'int_tst_rollback',
copy_indexes => DBMS_REDEFINITION.CONS_ORIG_PARAMS,
copy_triggers => TRUE,
copy_constraints => TRUE,
copy_privileges => TRUE,
ignore_errors => TRUE,
num_errors => num_errors);
END;
/
PL/SQL procedure successfully completed.
2.6 查詢DBA_REDEFINITION_ERRORS視圖是否有錯誤
SET LONG 8000
SET PAGES 8000
COLUMN OBJECT_NAME HEADING 'Object Name' FORMAT A20
COLUMN BASE_TABLE_NAME HEADING 'Base Table Name' FORMAT A10
COLUMN DDL_TXT HEADING 'DDL That Caused Error' FORMAT A40
SELECT OBJECT_NAME, BASE_TABLE_NAME, DDL_TXT FROM
DBA_REDEFINITION_ERRORS;
Object Name Base Table DDL That Caused Error
-------------------- ---------- ----------------------------------------
SYS_C007360 TEST_ROLLB ALTER TABLE "LEI"."INT_TST_ROLLBACK" ADD
ACK CONSTRAINT "TMP$$_SYS_C0073600" PRIMARY
KEY ("ID")
USING INDEX PCTFREE 10 INITRANS 2 MAXT
RANS 255
TABLESPACE "CNDBA" ENABLE NOVALIDATE
主鍵和索引相關的錯誤資訊可以忽略。
2.7 同步資料到臨時表
BEGIN
DBMS_REDEFINITION.SYNC_INTERIM_TABLE(
uname => 'lei',
orig_table => 'test_rollback',
int_table => 'int_tst_rollback');
END;
/
PL/SQL procedure successfully completed.
2.8 完成redefinition
BEGIN
DBMS_REDEFINITION.FINISH_REDEF_TABLE(
uname => 'lei',
orig_table => 'test_rollback',
int_table => 'int_tst_rollback');
END;
/
PL/SQL procedure successfully completed.
這裡會瞬間鎖表test_rollback。
2.9 收尾工作(選一執行)
2.9.1 如果redefined table性能沒有達到預期效果,則復原redefinition
BEGIN
DBMS_REDEFINITION.ROLLBACK(
uname => 'lei',
orig_table => 'test_rollback',
int_table => 'int_tst_rollback');
END;
/
2.9.2 相反,如果達到預期效果則終止復原操作
BEGIN
DBMS_REDEFINITION.ABORT_ROLLBACK(
uname => 'lei',
orig_table => 'test_rollback',
int_table => 'int_tst_rollback');
END;
/
2.10 删除臨時表
SQL> drop table lei.int_tst_rollback;
Table dropped.