We can encrypt a table using simple alter table command, However alter table command on big tables takes time and during this process, transaction will be blocked on that table.
So best solution to avoid downtime is to use dbms_redef method to move the table to a new encrypted tablespace.
ORIGINAL TABLE_NAME – > EMPLOYEE_ENTRY
INTERIM TABLE_NAME – > EMPLOYEE_ENTRY_INT
USERNAME -> DATATS
NEW TABLESPACE. – > DATATS_ENC
1. Create an encrypted tablespaces:
CREATE TABLESPACE DATATS_ENC datafile '+DATA' size 30g encryption using 'AES256' DEFAULT STORAGE(ENCRYPT);
SQL> select b.name,a.ENCRYPTIONALG from v$encrypted_tablespaces a,v$tablespace b where a.ts#=b.ts#;
NAME ENCRYPT
------------------------------ -------
DATATS_ENC AES256
SQL> select TABLESPACE_NAME,ENCRYPTED from dba_tablespaces where TABLESPACE_NAME='DATATS_ENC';
TABLESPACE_NAME ENC
------------------------------ ---
DATATS_ENC YES
2. Create a interim table by using the structure of the original table:
The original table is a partitioned table with interval partition. So i am using exdp and impdp to generate the proper DDL file.
expdp dumpfile=wm.dmp logfile=wm.log directory=T tables=DATATS.EMPLOYEE_ENTRY content=metadata_only
impdp dumpfile=wm.dmp logfile=wm.log directory=t sqlfile=tab.sql include=TABLE
Now open the tab.sql file and change the tablespace_name to DATATS_ENC .
SQL>@tab.sql
Table created
3. check the partition count in both the original and interim table:
SQL>select count(*) from dba_tab_partitions where table_owner='DATATS' and TABLE_NAME='EMPLOYEE_ENTRY';
COUNT(*)
---------
172
SQL>select count(*) from dba_tab_partitions where table_owner='DATATS' and TABLE_NAME='EMPLOYEE_ENTRY_INT';
COUNT(*)
---------
172
4. Check whether redef is posible or not:
SQL> SET SERVEROUTPUT ON
BEGIN
DBMS_REDEFINITION.CAN_REDEF_TABLE('DATATS','EMPLOYEE_ENTRY', DBMS_REDEFINITION.CONS_USE_ROWID);
END;
/SQL> SQL> 2 3 4
PL/SQL procedure successfully completed.
5. Now start the redef process:
You can use parallel for big tables for faster redef process.
ALTER SESSION FORCE PARALLEL DML PARALLEL 8;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 8;
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE(
uname => 'DATATS',
orig_table => 'EMPLOYEE_ENTRY',
int_table => 'EMPLOYEE_ENTRY_INT',
options_flag => DBMS_REDEFINITION.CONS_USE_ROWID);
END;
/
PL/SQL procedure successfully completed.
Elapsed: 00:10:53.12
6. Drop the not null constrains from the interim table ( if any):
SQL> select * from dba_constraints where owner='DATATS' and table_name='EMPLOYEE_ENTRY';
SQL> alter table "DATATS"."EMPLOYEE_ENTRY_INT" drop constraint SYS_C0013751;
Table altered.
SQL> alter table "DATATS"."EMPLOYEE_ENTRY_INT" drop constraint SYS_C0013752;
Table altered.
SQL> alter table "DATATS"."EMPLOYEE_ENTRY_INT" drop constraint SYS_C0013750;
Table altered.
7. Copy the dependents:
ALTER SESSION FORCE PARALLEL DML PARALLEL 16;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 16;
DECLARE
error_count pls_integer := 0;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('DATATS', 'EMPLOYEE_ENTRY', 'EMPLOYEE_ENTRY_INT', dbms_redefinition.cons_orig_params, TRUE,TRUE,TRUE,FALSE, error_count);
DBMS_OUTPUT.PUT_LINE('errors := ' || TO_CHAR(error_count));
END;
/
Session altered.
SQL>
Session altered.
SQL> SQL> SQL> 2 3 4 5 6 7
PL/SQL procedure successfully completed
8.Now do the final sync:
SQL> BEGIN
DBMS_REDEFINITION.SYNC_INTERIM_TABLE('DATATS', 'EMPLOYEE_ENTRY', 'EMPLOYEE_ENTRY_INT');
END;
/
PL/SQL procedure successfully completed.
9. Finish the redef process:
SQL> exec DBMS_REDEFINITION.FINISH_REDEF_TABLE('DATATS','EMPLOYEE_ENTRY','EMPLOYEE_ENTRY_INT');
PL/SQL procedure successfully completed.