Oracle NoLogging

Normalerweise wird für jede Änderung sowohl Redo als auch Undo Daten generiert, wobei die Redo Daten in Online Redo Logfile geschrieben werden. Das Erzeugen, schreiben und Archivieren der Redo Daten stellt in gewisser Weise einen Overhead dar. Nur so kann jedoch garantiert werden, dass eine Änderung dauerhaft ist. Es besteht die Möglichkeit, dass man Tables und Indizies mit NoLogging anlegt. Das reduziert zwar die Generierung von Redo, hat aber einen Einfluss auf die Recovery Möglichkeiten. Wird beim CREATE TABLE Nologging spezifiziert, so werden nachfolgende direct path inserts mit reduziertem Logging ausgeführt. Das Logging kann auf DB und Tablespace Ebene erzwungen werden.

-- default fuer neue objekte
alter tablespace users  nologging;

-- disallow nologging operations im tablespace
alter tablespace users  force logging;

-- erzwinge logging generell
alter database force logging;

Und bedenke: Probleme treten dann auf, wenn man sie so gar nicht gebrauchen kann.

Verzichtet man bei bestimmten aktionen auf das Logging, so verzicht man auf die Möglichkeit eines vollständigen Recoveries.

Ein konsitentes (TS)PITR auf einen Zeitpunkt zwischen NoLogging Aktion und Backup des betroffenen Datafiles ist nicht möglich!? 
 
SQL> select file#,to_char(UNRECOVERABLE_TIME,'yyyy-mm-dd:hh24:mi:ss') from v$datafile where unrecoverable_time is not null;

     FILE# TO_CHAR(UNRECOVERAB
---------- -------------------
         6 2016-06-10:13:41:57

SQL> select file#,to_char(COMPLETION_TIME,'yyyy-mm-dd:hh24:mi:ss') from v$backup_datafile where file# in ( select file# from v$datafile where unrecoverable_time is not null)order by 1,2;

     FILE# TO_CHAR(COMPLETION_
---------- -------------------
         6 2016-06-10:13:34:28
         6 2016-06-10:14:16:07

Ein PITR auf einen Zeitpunkt zwischen 13:41:57h und 14:16:07h könnte problematisch werden.

V$DATAFILE.UNRECOVERABLE_TIME
v$backup_datafile.COMPLETION_TIME

 
SQL> drop table t1 purge;

Table dropped.

SQL> create table t1 tablespace users
  2  as select rownum as id
  3  from dual connect by level <= 1e5;

Table created.

SQL> create index t1_i1 on t1 (id) tablespace users nologging;

Index created.

SQL>

RMAN> report unrecoverable database;

using target database control file instead of recovery catalog
Report of files that need backup due to unrecoverable operations
File Type of Backup Required Name
---- ----------------------- -----------------------------------
6    full or incremental     /u01/oradata/orcl1/users01.dbf

RMAN>

Nach einem fehlerfreien Restore/Recovery kann ein mit NoLogging erzeugter Index nicht mehr verwendet werden.

 

SQL> select count(*) from t1;

  COUNT(*)
----------
    100000

SQL> select count(*) from t1 where id=300;
select count(*) from t1 where id=300
       *
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 6, block # 476)
ORA-01110: data file 6: '/u01/oradata/orcl1/users01.dbf'
ORA-26040: Data block was loaded using the NOLOGGING option


SQL> select /*+ full(t1) */ count(*) from t1 where id=300;

  COUNT(*)
----------
         1

SQL> alter index t1_i1 unusable;

Index altered.

SQL> alter index t1_i1 rebuild;

Index altered.

SQL> select count(*) from t1 where id=300;

  COUNT(*)
----------
         1

SQL>
SQL> select count(*) from t1 where id=300;

  COUNT(*)
----------
         1

SQL>

 
select owner,count(*) from dba_tables where LOGGING = 'NO' group by owner;
select owner,count(*) from dba_indexes where LOGGING = 'NO' group by owner;
select tablespace_name,logging from dba_tablespaces order by 2,1;
select force_logging from v$database;
alter database force logging;
alter database no force logging;
select file#,to_char(UNRECOVERABLE_TIME,'yyyy-mm-dd:hh24:mi:ss') from v$datafile;

Wird nur ein Index mit NoLogging erstellt, kann man den rebuilden, nachdem man ihn unusable gesetzt hat. Wird jedoch auf eine Tabelle NoLogging verwendet, kann es zu Datenverlust kommen. Nur per Tuncate könnten die korrupten DB Blöcke entfernt werden.

Siehe auch das Beispiel von Uwe Hesse.