Redefine a Table Online with DBMS_REDEFINITION, No DML Blocking
Redefine a Table Online with DBMS_REDEFINITION, No DML Blocking
Purpose
A DBA moving a table to a new tablespace, adding compression, or rebuilding a badly fragmented segment has one hard requirement: users can't lose access to that table while the change is happening. For decades the available tools — CREATE TABLE AS SELECT plus a rename, or a plain ALTER TABLE MOVE — all lock the table for at least part of the operation, even if only briefly. DBMS_REDEFINITION restructures a table while it stays fully readable and writable the entire time.
The mechanism behind that is not magic — it's materialized view logs. Oracle builds incrementally maintainable local materialized views against the original table, and those logs track every change made to it while the redefinition is in progress. When the interim table is synchronized, Oracle replays the tracked changes into it, which is what lets an application keep issuing DML against the original table for the whole window instead of freezing at the start. Subprograms in the package run with invokers' rights, and Oracle splits access into two modes: USER mode, where a user redefines a table in their own schema, and FULL mode, where a user holding the right ANY privileges can redefine a table in any schema.
This post covers the full multi-step workflow — checking eligibility, starting the redefinition, cloning dependent objects, synchronizing, and finishing or rolling back — plus the single-step REDEF_TABLE procedure that folds several of those steps into one call for straightforward storage changes. It also covers the privilege split between USER and FULL mode in more detail, and a data-dictionary side effect of the redefinition process that catches DBAs who haven't seen it before: what happens to audit policies once the operation completes.
Code
1-- Step 1: original and interim tables, same structure, different tablespaces
2CREATE TABLE emp (
3 empno NUMBER(4,0) PRIMARY KEY,
4 ename VARCHAR2(10),
5 job VARCHAR2(9),
6 mgr NUMBER(4,0),
7 hiredate DATE,
8 sal NUMBER(7,2),
9 comm NUMBER(7,2),
10 deptno NUMBER(2,0)
11) TABLESPACE myts;
12
13CREATE TABLE emp_int (
14 empno NUMBER(4,0) PRIMARY KEY,
15 ename VARCHAR2(10),
16 job VARCHAR2(9),
17 mgr NUMBER(4,0),
18 hiredate DATE,
19 sal NUMBER(7,2),
20 comm NUMBER(7,2),
21 deptno NUMBER(2,0)
22) TABLESPACE compressed_ts;
23
24-- Step 2: confirm the table is a valid redefinition candidate before starting
25EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('SCOTT', 'EMP', DBMS_REDEFINITION.CONS_USE_ROWID);
26
27-- Step 3: start the redefinition, rollback kept available
28BEGIN
29 DBMS_REDEFINITION.START_REDEF_TABLE(
30 uname => 'SCOTT',
31 orig_table => 'EMP',
32 int_table => 'EMP_INT',
33 enable_rollback => TRUE);
34END;
35/
36
37-- Step 4: clone grants, triggers, constraints, and indexes onto the interim table
38DECLARE
39 num_errors PLS_INTEGER;
40BEGIN
41 DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(
42 uname => 'SCOTT',
43 orig_table => 'EMP',
44 int_table => 'EMP_INT',
45 copy_indexes => DBMS_REDEFINITION.CONS_ORIG_PARAMS,
46 copy_triggers => TRUE,
47 copy_constraints => TRUE,
48 copy_privileges => TRUE,
49 num_errors => num_errors);
50 DBMS_OUTPUT.PUT_LINE('Errors: ' || num_errors);
51END;
52/
53
54-- Step 5: keep the interim table in sync -- run repeatedly while evaluating (e.g. hourly)
55EXEC DBMS_REDEFINITION.SYNC_INTERIM_TABLE('SCOTT', 'EMP', 'EMP_INT');
56
57-- Step 6a: satisfied with the result -- commit the redefinition
58EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE('SCOTT', 'EMP', 'EMP_INT');
59
60-- Step 6b: not satisfied -- roll back to the original table instead
61EXEC DBMS_REDEFINITION.ROLLBACK('SCOTT', 'EMP', 'EMP_INT');
62
63-- Step 7: once no rollback will be needed, close that door and free the tracking objects
64EXEC DBMS_REDEFINITION.ABORT_ROLLBACK('SCOTT', 'EMP', 'EMP_INT');
65
66-- Single-step alternative: REDEF_TABLE folds the workflow above into one call
67-- for a straightforward storage change -- tablespace, table compression,
68-- index compression, and LOB storage/compression together
69BEGIN
70 DBMS_REDEFINITION.REDEF_TABLE(
71 uname => 'PM',
72 tname => 'PRINT_ADS',
73 table_compression_type => 'ROW STORE COMPRESS ADVANCED',
74 table_part_tablespace => 'USERS',
75 index_key_compression_type => 'COMPRESS 1',
76 index_tablespace => 'USERS',
77 lob_compression_type => 'COMPRESS HIGH',
78 lob_tablespace => 'USERS',
79 lob_store_as => 'SECUREFILE');
80END;
81/
Code Breakdown
Step 2: CAN_REDEF_TABLE
This is the mandatory first call. It checks whether the target table qualifies for online redefinition and raises an error if it doesn't, before anything else has been touched. The options_flag parameter selects the redefinition method: DBMS_REDEFINITION.CONS_USE_PK (the default) redefines using the primary key or a pseudo-primary key — a unique key whose columns are all NOT NULL; DBMS_REDEFINITION.CONS_USE_ROWID redefines using rowids instead, which is the option a table with no primary key and no qualifying unique key has to use.
Step 3: START_REDEF_TABLE
This begins the actual redefinition process against a manually created, empty interim table in the same schema as the original. From this point until FINISH_REDEF_TABLE or ABORT_REDEF_TABLE is called, both tables exist and the materialized-view-log mechanism is actively tracking changes to the original. Setting enable_rollback => TRUE keeps the option open to undo everything later with the ROLLBACK procedure.
Step 4: COPY_TABLE_DEPENDENTS
The interim table starts out as a structural copy only — it does not automatically carry the original's grants, triggers, constraints, or indexes. COPY_TABLE_DEPENDENTS clones those across and registers them as dependent objects of the redefinition. copy_indexes => DBMS_REDEFINITION.CONS_ORIG_PARAMS tells it to clone indexes using the same storage parameters the originals used, rather than defaults. The num_errors output parameter reports how many of the requested clones failed, so a script can check it rather than assuming success.
Step 5: SYNC_INTERIM_TABLE
Because the original table stays fully live during the whole process, the interim table drifts out of sync with every DML statement that runs against the original after START_REDEF_TABLE. SYNC_INTERIM_TABLE applies the tracked changes and brings it current again. Calling this repeatedly — say, once an hour — while evaluating a change keeps the eventual FINISH_REDEF_TABLE call fast, since less catching-up remains to do at cutover.
Step 6: FINISH_REDEF_TABLE, ROLLBACK, and ABORT_ROLLBACK
FINISH_REDEF_TABLE performs the actual swap: a final synchronization runs, then the original and interim tables exchange identities, with the interim table's structure taking over the original table's name. ROLLBACK is the opposite path — available only when enable_rollback was set to TRUE at START_REDEF_TABLE — and restores the original table to its pre-redefinition state. ABORT_ROLLBACK doesn't roll anything back itself; it terminates the possibility of a later rollback, releasing the objects that made it available once the DBA is confident the change should stick.
Single-step REDEF_TABLE
REDEF_TABLE is a push-button alternative that runs several of the steps above internally and is built for a specific case: changing a table's storage properties — tablespace, compression type, index compression, LOB storage — without needing to hand-manage an interim table, dependent-object cloning, or a sync loop. It still supports enable_rollback, but the reference documentation is explicit that rollback is not supported when REDEF_TABLE itself is the procedure used to perform the redefinition — a distinction worth checking before assuming the flag behaves identically to the multi-step path.
Key Points
- The mechanism is materialized view logs, not a lock. Oracle tracks changes to the original table through incrementally maintainable materialized views, which is what lets DML continue against it throughout the process.
- CAN_REDEF_TABLE is not optional. It's the documented first step, and it raises an error outright if the table isn't a valid candidate rather than letting a later step fail unpredictably.
- The redefinition key defaults to primary key, not rowid.
CONS_USE_PK(primary key or a NOT-NULL unique key) is the default method;CONS_USE_ROWIDis the explicit fallback for a table without one. - REDEF_TABLE does not support rollback, even though the parameter exists on the call — only the multi-step
START_REDEF_TABLE/ROLLBACKpath does. - Object IDs swap at FINISH_REDEF_TABLE, not names. The interim table takes on the original table's object ID during the swap — which has a direct consequence for anything keyed to that ID (see below).
- Two privilege modes govern who can redefine what. USER mode covers a user redefining their own schema's table; FULL mode, requiring the ANY-level privileges, covers redefining a table in someone else's schema.
Insights and Best Practices
Recheck audit policies after a redefinition completes
Because the interim table takes on the original table's object ID during the swap, and Oracle audit policies are tied to object IDs rather than object names, any audit policy that existed on a table before it was redefined keeps auditing "the same" object afterward — which is now, physically, the former interim table. This is easy to overlook because nothing about the table's name or apparent identity changed from the application's point of view. Checking existing audit policies against a table right after redefining it, and adjusting them if the intent was actually to audit a specific physical object rather than a logical name, closes that gap before it becomes a compliance surprise.
Match privileges to the mode you actually need
Redefining a table in your own schema (USER mode) needs execute privilege on the DBMS_REDEFINITION package plus CREATE TABLE and CREATE MATERIALIZED VIEW; the COPY_TABLE_DEPENDENTS step additionally needs CREATE TRIGGER if the table has triggers to clone. Redefining a table in another schema (FULL mode) needs a wider set — CREATE ANY TABLE, ALTER ANY TABLE, DROP ANY TABLE, LOCK ANY TABLE, and SELECT ANY TABLE, plus CREATE ANY TRIGGER and CREATE ANY INDEX if COPY_TABLE_DEPENDENTS is run against a table outside the connecting user's own schema. Granting the FULL-mode privilege set to an account that only ever needs USER mode is broader access than the job requires.
Use the sync window to actually evaluate the change
The gap between START_REDEF_TABLE and FINISH_REDEF_TABLE isn't just plumbing — it's a live evaluation window. A table moved to a different tablespace, or given a different compression setting, can be checked for real query performance during that window with SYNC_INTERIM_TABLE calls keeping it current, and the decision to commit or roll back can be made from actual observed behavior rather than a guess made in advance.
Reach for REDEF_TABLE only when rollback isn't a requirement
Because REDEF_TABLE doesn't support rolling back, it fits a narrower case than the full multi-step workflow: a storage-property change the DBA is already confident about, where the value of a one-call interface outweighs the value of a safety net. For a change carrying more uncertainty — a first attempt at a new compression setting on a business-critical table, for instance — the multi-step path with enable_rollback => TRUE is the more conservative choice.
Drop the interim table once FINISH_REDEF_TABLE has run
After a successful FINISH_REDEF_TABLE, the table that started as the interim table has taken over the original name, and the name that was passed in as int_table now refers to what's left of the old structure. That leftover object still occupies space and should be dropped once it's no longer needed, rather than left sitting in the schema as an orphaned artifact of the process.
When to Use This
- Reclaiming space or reducing fragmentation on a large table without a maintenance window.
- Moving a table to a different tablespace while the application keeps reading and writing it.
- Adding or changing table, index, or LOB compression on a table that already holds production data.
- Evaluating a storage change against real query load before committing to it, with the option to roll back if it doesn't help.
- Standardizing storage settings — tablespace placement, compression type — across a table where
ALTER TABLE MOVE's DML restriction isn't acceptable.
Troubleshooting Common Issues
CAN_REDEF_TABLE raises an error. The table isn't currently a valid redefinition candidate. If the call used the default CONS_USE_PK method, confirm the table actually has a primary key or a qualifying NOT-NULL unique key — if it doesn't, CONS_USE_ROWID is the alternative to pass instead.
A privilege error appears partway through the workflow. Confirm the mode: redefining a table in your own schema needs CREATE TABLE and CREATE MATERIALIZED VIEW at minimum (plus CREATE TRIGGER if COPY_TABLE_DEPENDENTS needs to clone triggers); redefining a table in another schema needs the broader FULL-mode privilege set, including CREATE ANY TABLE and ALTER ANY TABLE.
ROLLBACK fails or isn't available after using REDEF_TABLE. This is expected — online redefinition rollback is not supported when REDEF_TABLE was the procedure used to perform the redefinition. Only the multi-step START_REDEF_TABLE path, with enable_rollback => TRUE, supports a later ROLLBACK call.
An audit policy on a table stops matching what's expected after a redefinition. Check the table's object ID — the redefinition swapped it with the interim table's ID at FINISH_REDEF_TABLE, and audit policies key on object ID rather than object name.
References
- DBMS_REDEFINITION — PL/SQL Packages and Types Reference 19c - canonical syntax, constants, and operational notes for the full package, including the object-ID-swap and audit-policy behavior and the REDEF_TABLE rollback limitation
- Exploring the Nuts and Bolts of DBMS Online Redefinition — Oracle MAA blog - Oracle's own walkthrough of the USER/FULL mode privilege split and a worked REDEF_TABLE example changing tablespace, table compression, index compression, and LOB storage in one call
- Online reorganization of a table using Oracle DBMS_REDEFINITION package - a step-by-step run through CAN_REDEF_TABLE, manually creating the interim table, START_REDEF_TABLE, COPY_TABLE_DEPENDENTS, SYNC_INTERIM_TABLE, and FINISH_REDEF_TABLE, ending with dropping the interim table
Posts in this series
- Oracle Recompile Invalid Objects with utlrp.sql
- Identify and Fix Invalid Objects in Oracle Database
- Search Objects in Oracle Database
- Query The Oracle Database Procedure Source Code
- Oracle DBA_OBJECTS: List All Objects Owned by a User
- Unveiling the Mystery Oracle for Object Size Analysis
- Find Tables Containing a Specific Column in Oracle Database
- Oracle DBMS_METADATA.GET_DDL: Extract Object DDL
- dba_segments: Find Oracle Table Storage Usage by User
- Oracle PL/SQL: SHOW ERRORS and dba_errors Explained
- Redefine a Table Online with DBMS_REDEFINITION, No DML Blocking