18c: Schutz vor "Lost Writes"

"Lost Writes" sind ein selten auftretendes Phänomen, für die es ab der Oracle Datenbankversion 18c einen Schutz gibt, der verhindert, dass durch "Lost Writes" Dateninkonsistenzen entstehen. Was sind "Lost Writes" und wie sieht der Schutz aus? Lesen Sie dazu diesen Tipp.

Eigentlich soll es ja nie passieren: Eine Software schreibt etwas auf die Festplatte und die meldet auch einen erfolgreichen Schreibvorgang obwohl die dauerhafte Speicherung auf der Festplatte noch nicht abgeschlossen ist. Und dann passiert es: ein Ereignis sorgt dafür, dass der endgültige Schreibvorgang auf die Festplatte verhindert wird. Die Software hatte ja eine Erfolgsmeldung bekommen und geht von der erfolgreichen Speicherung nun leider irrtümlich aus - man spricht nun von einem "Lost Write". Wenn der betroffene Speicherblock später aufgerufen wird, hat er einen älteren Stand, als die Software annimmt.

Das oben beschriebene Szenario sollte eigentlich niemals auftreten und in der Praxis tritt es auch sehr selten auf, aber durch die heutigen Cache-Technologien bei den Festspeichern ist es durchaus denkbar. Übertragen auf die Oracle Datenbank betrifft das oben beschriebene Szenario die Datenblöcke bzw. Datendateien. Der Database Writer (DBWR) schreibt diese Blöcke aus dem Buffer Cache und wartet auf eine Erfolgsmeldung des Storage. Dieser kann wiederum Caches nutzen, die ausfallen können - wie schon geschrieben ein Vorfall, der sehr selten ist. Wenn nun ein Datenblock später wieder in den Buffer Cache gelesen wird, dieser aber beim letzten Schreibvorgang nicht wirklich erfolgreich auf die Festplatte geschrieben wurde, würde eine veraltete Version geladen und die Daten wären nicht mehr konsistent.

Für hochverfügbare Datenbanken, die einen durch Cache-Technologie hochperformanten Storage nutzen ist es sinnvoll, dafür zu sorgen, dass beim Lesen eines Blocks geprüft wird, dass dieser Block auch wirklich dem letzten durch die Software gespeicherten Stand entspricht.

Die Oracle Datenbank hat in jedem Oracle Datenblock eine Markierung, bei welcher SCN (System Change Number) die letzte Datenänderung im Datenblock vorgenommen wurde. Darüber kann man also testen, ob ein vorliegender Datenblock aktuell ist. In Oracle 11g wurde der Instanzparameter DB_LOST_WRITE_PROTECT eingeführt, um einen ersten Schutz vor Lost Writes zu implementieren. Dieser wirkt aber nur in einer Physical Standby Database Umgebung und sorgt dafür, dass auf der Seite der Physical Standby Datenbank beim Apply der Redo Logs (was ja einem Recovery-Vorgang entspricht) die auch in den Log-Einträgen stehenden SCNs mit denen in den Datenblöcken auf der Standby Seite verglichen werden. Letztlich wird damit sichergestellt, dass sich ein Lost Write nicht auch auf die Standby Datenbank überträgt. Im Fehlerfall kann dann von der Primärdatenbank auf die Standbydatenbank umgeschaltet werden, wobei je nach Betriebsmodus der Standbyumgebung auch die letzten Transaktionen verloren gehen können.

Ab Oracle 18c gibt es den Schutz vor Lost Writes auch ohne Standby Konfigurationen. Dabei wird die Idee verfolgt, dass man diesen Schutz ja auch aufbauen kann, wenn man sich für jeden benutzten Datenblock die letzte SCN zusätzlich merken würde. Genau dieses übernehmen die in Oracle 18c Enterprise Edition eingeführten "Shadow Tablespaces". Diese Tablespaces speichern also keine Nutzdaten, sondern nur die letzten SCNs der Oracle Datenblöcke. Die Shadow Tablespaces benötigen dabei also viel weniger Platz als normale Tablespaces. Die Empfehlung ist, dass man ca. 2% von dem Speicher einplant, den man über dieses Feature schützen möchte. Das Feature "Lost Write Protection" kann für einzelne Tablespaces oder Datendateien eingesetzt werden. Dabei kann berücksichtigt werden, welcher Storage für welche Datendateien eingesetzt wird, bzw. eine Unterscheidung nach Wichtigkeit vorgenommen werden. Wenn beim Lesen eines Oracle Datenblocks über den Vergleich mit der im Shadow Tablespace gespeicherten SCN festgestellt wird, dass der Datenblock veraltet ist, erfolgt die Fehlermeldung "ORA-65478: shadow lost write protection - found lost write" und die Datenbankadministration muß ein Recovery anstoßen.

Der Schutz wirkt sowohl für normale DML Operationen als auch für SQL*Loader im Conventional Path Modus.

Für eine Oracle Datenbank können ein oder mehrere Shadow Tablespaces angelegt werden. Danach wird deren Nutzung nur noch aktiviert. Die Zuordnung, in welchem Shadow Tablespace die SCN eines Datenblocks gespeichert wird, übernimmt das Datenbanksystem, die Datenbankadministration hat darauf keinen Einfluß. Shadow Tablespaces können für Non-CDBs, CDB und PDBs erstellt werden.

Das Vorgehen ist dabei recht einfach:

 
Schritt 1: Shadow Tablespace anlegen

Zunächst werden ein oder mehrere Shadow Tablespaces als Bigfile Tablespace erstellt mit

CREATE BIGFILE TABLESPACE <ts_name> DATAFILE '<filename>' SIZE 20M LOST WRITE PROTECTION;

Also zum Beispiel:

CREATE BIGFILE TABLESPACE shadow_cdb_lwp1 DATAFILE '/u02/app/oracle/oradata/ORCL/shadow_lwp1_pdb1.dbf' SIZE 10M LOST WRITE PROTECTION;

Ob ein Tablespace ein Shadow Tablespace ist, oder nicht, können Sie in DBA_TABLESPACES abfragen:

select tablespace_name,status,contents from dba_tablespaces;

TABLESPACE_NAME 	       STATUS	 CONTENTS
------------------------------ --------- ---------------------
SYSTEM			       ONLINE	 PERMANENT
SYSAUX			       ONLINE	 PERMANENT
UNDOTBS1		       ONLINE	 UNDO
TEMP			       ONLINE	 TEMPORARY
USERS			       ONLINE	 PERMANENT
SHADOW_CDB_LWP1 	       ONLINE	 LOST WRITE PROTECTION

 
Schritt 2: LOST WRITE PROTECTION für die Datenbank aktivieren

Nach dem Erstellen der Shadow Tablespaces muß das Feature "Lost Write Protection" für die Datenbank eingeschaltet werden:

Für Non-CDBs oder CDBs:
ALTER DATABASE ENABLE LOST WRITE PROTECTION;

Für PDBs:
ALTER PLUGGABLE DATABASE ENABLE LOST WRITE PROTECTION;

Damit ist die Datenbank aber nur vorbereitet, das Feature immer noch nicht aktiv.

 
Schritt 3: Schutz für Tablespaces oder Datendateien einschalten

Jetzt muß noch für Tablespaces oder Datendateien der Schutz eingeschaltet werden:

ALTER TABLESPACE <ts_name> ENABLE LOST WRITE PROTECTION;
oder
ALTER DATABASE DATAFILE '<db_filename>' ENABLE LOST WRITE PROTECTION;
bzw.
ALTER PLUGGABLE DATABASE DATAFILE '<db_filename>' ENABLE LOST WRITE PROTECTION;

Falls Sie es zuvor versäumt haben, die Datenbank in den Modus "LOST WRITE PROTECTION" zu versetzen (siehe Schritt 2), erscheint die folgende Fehlermeldung:

SQL> ALTER TABLESPACE users ENABLE LOST WRITE PROTECTION;
ALTER TABLESPACE users ENABLE LOST WRITE PROTECTION
*
ERROR at line 1:
ORA-65474: lost write tablespace does not exist or has insufficient space or lost write is off

Im Data Dictionary kann man den Status in den View DBA_TABLESPACES oder DBA_DATA_FILES sehen:

desc dba_tablespaces
 Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 TABLESPACE_NAME			   NOT NULL VARCHAR2(30)
 BLOCK_SIZE				   NOT NULL NUMBER
 INITIAL_EXTENT 				    NUMBER
 NEXT_EXTENT					    NUMBER
 MIN_EXTENTS				   NOT NULL NUMBER
 MAX_EXTENTS					    NUMBER
 MAX_SIZE					    NUMBER
 PCT_INCREASE					    NUMBER
 MIN_EXTLEN					    NUMBER
 STATUS 					    VARCHAR2(9)
 CONTENTS					    VARCHAR2(21)
 LOGGING					    VARCHAR2(9)
 FORCE_LOGGING					    VARCHAR2(3)
 EXTENT_MANAGEMENT				    VARCHAR2(10)
 ALLOCATION_TYPE				    VARCHAR2(9)
 PLUGGED_IN					    VARCHAR2(3)
 SEGMENT_SPACE_MANAGEMENT			    VARCHAR2(6)
 DEF_TAB_COMPRESSION				    VARCHAR2(8)
 RETENTION					    VARCHAR2(11)
 BIGFILE					    VARCHAR2(3)
 PREDICATE_EVALUATION				    VARCHAR2(7)
 ENCRYPTED					    VARCHAR2(3)
 COMPRESS_FOR					    VARCHAR2(30)
 DEF_INMEMORY					    VARCHAR2(8)
 DEF_INMEMORY_PRIORITY				    VARCHAR2(8)
 DEF_INMEMORY_DISTRIBUTE			    VARCHAR2(15)
 DEF_INMEMORY_COMPRESSION			    VARCHAR2(17)
 DEF_INMEMORY_DUPLICATE 			    VARCHAR2(13)
 SHARED 					    VARCHAR2(13)
 DEF_INDEX_COMPRESSION				    VARCHAR2(8)
 INDEX_COMPRESS_FOR				    VARCHAR2(13)
 DEF_CELLMEMORY 				    VARCHAR2(14)
 DEF_INMEMORY_SERVICE				    VARCHAR2(12)
 DEF_INMEMORY_SERVICE_NAME			    VARCHAR2(1000)
 LOST_WRITE_PROTECT				    VARCHAR2(7)
 CHUNK_TABLESPACE				    VARCHAR2(1)

Die Spalte "LOST_WRITE_PROTECT" zeigt an, ob für einen Tablespace das Feature aktiviert ist, also

alter tablespace users ENABLE LOST WRITE PROTECTION;

Tablespace altered.

SQL> select TABLESPACE_NAME,LOST_WRITE_PROTECT from dba_tablespaces;

TABLESPACE_NAME 	       LOST_WR
------------------------------ -------
SYSTEM			       OFF
SYSAUX			       OFF
UNDOTBS1		       OFF
TEMP			       OFF
USERS			       ENABLED
SHADOW_CDB_LWP1 	       OFF

Damit wird dieses natürlich auch für alle Datendateien dieses Tablespace angezeigt:

desc dba_data_files
 Name					   Null?    Type
 ----------------------------------------- -------- ----------------------------
 FILE_NAME					    VARCHAR2(513)
 FILE_ID					    NUMBER
 TABLESPACE_NAME				    VARCHAR2(30)
 BYTES						    NUMBER
 BLOCKS 					    NUMBER
 STATUS 					    VARCHAR2(9)
 RELATIVE_FNO					    NUMBER
 AUTOEXTENSIBLE 				    VARCHAR2(3)
 MAXBYTES					    NUMBER
 MAXBLOCKS					    NUMBER
 INCREMENT_BY					    NUMBER
 USER_BYTES					    NUMBER
 USER_BLOCKS					    NUMBER
 ONLINE_STATUS					    VARCHAR2(7)
 LOST_WRITE_PROTECT				    VARCHAR2(7)

select file_name,LOST_WRITE_PROTECT from dba_data_files;

FILE_NAME                                  LOST_WR
------------------------------------------ -------
/u02/app/oracle/oradata/ORCL/system01.dbf  OFF
/u02/app/oracle/oradata/ORCL/sysaux01.dbf  OFF
/u02/app/oracle/oradata/ORCL/users01.dbf   ENABLED
/u02/app/oracle/oradata/ORCL/undotbs01.dbf OFF

 
Verhalten bei Lost Writes

Falls ein Lost Write auftritt und Sie auf betroffene Daten zugreifen erfolgt die folgende Fehlermeldung:

SQL> SELECT * FROM no_lost_write;

SELECT * FROM no_lost_write
              *
ERROR at line 1:
ORA-65478: shadow lost write protection - found lost write

 
Abschalten des Schutzes

Sie können den Schutz auf der Ebene der Datenbank abschalten mit

ALTER DATABASE DISABLE LOST WRITE PROTECTION;
oder
ALTER PLUGGABLE DATABASE DISABLE LOST WRITE PROTECTION;

Auf der Ebene der Tablespaces bzw. Datendateien können Sie den Schutz

  • aussetzen (SUSPEND):
    es werden keine SCN mehr im Shadow Tablespace gespeichert, aber die bereits gespeicherten SCNs verbleiben im Shadow Tablespace. Dieses ist sinnvoll für kontrollierte Situationen, in denen gesichert ist, dass keine "Lost Writes" auftreten können.
  • abschalten und löschen (REMOVE):
    Der Schutz wird abgeschaltet und bereits gespeicherte SCNs werden gelöscht (bzw. als freier Speicher markiert und später überschrieben).

Die Kommandos sind sprechend:

ALTER TABLESPACE users SUSPEND LOST WRITE PROTECTION;
ALTER TABLESPACE users REMOVE LOST WRITE PROTECTION;

ALTER DATABASE DATAFILE           '/u02/app/oracle/oradata/ORCL/users01.dbf' SUSPEND LOST WRITE PROTECTION;
ALTER PLUGGABLE DATABASE DATAFILE '/u02/app/oracle/oradata/ORCL/users01.dbf' SUSPEND LOST WRITE PROTECTION;

ALTER DATABASE DATAFILE           '/u02/app/oracle/oradata/ORCL/users01.dbf' REMOVE LOST WRITE PROTECTION;
ALTER PLUGGABLE DATABASE DATAFILE '/u02/app/oracle/oradata/ORCL/users01.dbf' REMOVE LOST WRITE PROTECTION;

 
Fazit

Ab Oracle 18c bietet die Oracle Datenbank einen Schutz vor Schäden an Daten durch Lost Writes durch Shadow Tablespaces.

 
Lizenzhinweis

Lost Write Protection ist Bestandteil der Enterprise Edition. Dieses ist beschrieben im Licensing Guide.

 
Verfügbarkeit und Download

Weitere Informationen


 

Zurück zum Anfang des Artikels

Zurück zur Community-Seite
 

Visit the Oracle Blog

 

Contact Us

Oracle

Integrated Cloud Applications & Platform Services