Certaines requêtes DDL offrent la possibilité de ne pas générer des enregistrements dans les redo log via la clause NOLOGGING. Le mode nologging permet donc dans certains cas d’accélérer des traitements, ceux-ci pouvant facilement être récupérables à travers des mécanismes externes à la base de données. Ce mode peut cependant avoir des conséquences fâcheuses comme nous allons le constater et ce pas uniquement dans le contexte de configurations comme Oracle DataGuard.
Dans le cadre de mon activité de consultant, je rencontre fréquemment des bases de données qui sont en mode NOLOGGING. Quelle en est la signification et quelles peuvent être les implications d’une telle configuration ?
Pour répondre à cette question nous allons nous intéresser au comportement d’une instance de base de données en mode NOLOGGING.
SQL> select force_logging from v$database; FORCE_LOGGING --- NO
Les tablespaces de l’instance sont eux par contre en mode LOGGING :
SQL> select tablespace_name , logging from dba_tablespaces; TABLESPACE_NAME LOGGING ------------------------------ --------- SYSTEM LOGGING SYSAUX LOGGING UNDOTBS1 LOGGING TEMP NOLOGGING USERS LOGGING REPO_RMAN LOGGING REPO_RMAN2 LOGGING
Nous créons une table test_redo et nous la plaçons en mode NOLOGGING:
SQL> create table test_redo as select * from all_objects where 1=2; Table created. SQL> alter table test_redo nologging; Table altered.
En insérant des données dans la table redo_test, on visualise une activité des redologs :
SQL> set autotrace on statistics; SQL> insert into test_redo select * from all_objects; 71890 rows created. Statistics ---------------------------------------------------------- 1527 recursive calls 9938 db block gets 50166 consistent gets 859 physical reads 8430816 redo size 674 bytes sent via SQL*Net to client 619 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1523 sorts (memory) 0 sorts (disk) 71890 rows processed
Si on réalise une insertion en direct load via le hint APPEND, l’activité des redologs est moins importante, il y a eu beaucoup moins d’écriture dans les redologs :
SQL> insert /*+ APPEND */ into test_redo select * from all_objects; 71890 rows created. Statistics ---------------------------------------------------------- 225 recursive calls 1380 db block gets 47267 consistent gets 0 physical reads 28304 redo size 663 bytes sent via SQL*Net to client 633 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1501 sorts (memory) 0 sorts (disk) 71890 rows processed
Si nous interrogeons la vue v$datafile, nous pouvons visualiser qu’il y a eu une activité qui n’a pas été écrite dans les redologs :
SQL> SELECT NAME, UNRECOVERABLE_CHANGE#, 2 TO_CHAR (UNRECOVERABLE_TIME,'DD-MON-YYYY HH:MI:SS') 3 FROM V$DATAFILE; NAME UNRECOVERABLE_CHANGE# TO_CHAR(UNRECOVERABLE_TIME /u01/database/DB112/system01.dbf 0 /u01/database/DB112/sysaux01.dbf 0 /u01/database/DB112/undotbs01.dbf 0 /u01/database/DB112/users01.dbf 2048947 18-APR-2011 05:07:10
A présent, restaurons l’instance de base de données à un instant t postérieur à l’insertion en direct load, ces données ne seront pas restaurées un message de bloc corrompu apparaitra :
SQL> select count(*) from redo_test; select count(*) from redo_test * ERROR at line 1: ORA-01578: ORACLE data block corrupted (file # 4, block # 1410) ORA-01110: data file 4: '/u01/database/DB112/users01.dbf' ORA-26040: Data block was loaded using the NOLOGGING option
Les opérations en nologging sont plus rapides puisqu’il n’y a pas d’écriture dans les redologs :
SQL> set timing on SQL> create table redo_test as select * from all_objects where 1=2; Table created. Elapsed: 00:00:01.29 SQL> create table redo_test_nolog nologging as select * from all_objects where 1=2; Table created. Elapsed: 00:00:00.56 SQL> insert into redo_test select * from all_objects; 71892 rows created. Elapsed: 00:00:05.58 SQL> insert /* +APPEND */ into redo_test_nolog select * from all_objects; 71892 rows created. Elapsed: 00:00:03.62
Regardons maintenant si une table créée en mode NOLOGGING a des conséquences sur toutes les opérations DML. Nous allons détruire toutes les lignes de la table redo_test_nolog et effectuer un rollback :
SQL> create table redo_test_nolog nologging as select * from all_objects; Table created. SQL> delete from redo_test_nolog; 71892 rows deleted. SQL> rollback; Rollback complete. SQL> select count(*) from redo_test_nolog; COUNT(*) 71892
Comme précisé dans la documentation Oracle :
“The NOLOGGING clause also specifies that subsequent direct loads using SQL*Loader and direct load INSERT operations are not logged. Subsequent DML statements (UPDATE, DELETE, and conventional path insert) are unaffected by the NOLOGGING attribute of the table and generate redo.”
En résumé les opérations en nologging peuvent faire gagner du temps, mais il faut être conscient du risque pris lors de telles opérations. Toute opération effectuée en direct load insert implique nécessairement un backup de l’instance.