# [23ai] Shadow Tablespaces

*El artículo también se encuentra publicado en Ingles* [***English version***](https://dbaintheshadow.com/23ai-shadow-tablespaces)*.*

En el artículo de hoy vamos hablar sobre un tipo de ***tablespace*** que se “encuentran” nunca mejor dicho, en la sombra de la página oficial de Oracle, son los **Shadow Tablespaces**.

Este tipo de ***tablespace*** no es un **feature** de la **23ai**, sino que existen desde la **18c** en adelante.

Antes de entrar en detalle, no tiene ningún tipo de relación con el parámetro *DB\_LOST\_WRITE\_PROTECT*, podríamos decir que tiene un propósito parecido pero van por caminos diferentes.

## **Propósito**

**Shadow Tablespace** es un ***tablespace***, en 23ai de tipo **bigfile**, destinado a protegernos rápidamente cuando se producen pérdidas de escritura en ***tablespaces*** o ***datafiles***, minimizando el tiempo requerido para reparar una base de datos.

## **¿Cómo trabaja?**

Para poder usar esta funcionalidad, necesitamos un **shadow tablespace** y un **no-shadow tablespace**.

Vamos a ver un pequeño modelo de como funciona:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1759578208948/10488d8d-3acd-46d3-b3ee-43fec08a70d1.png align="center")

Aquí podemos ver un **shadow tablespace “***STTab001***”** rastreando dos **tablespaces** muy distintos entre si, uno es de tipo **bigfile “***Tab002***”**, y el otro es de tipo **smallfile “***SmallTab001***”.**

Esta pequeña diferencia es que quiero que veamos como podemos ligarlos a un ***tablespace*** o un ***datafile***, y la manera de tener en 23ai varios ***datafiles*** en un **tablespace**, es definiéndolo de tipo **smallfile** (**bigfile** solo puede tener un ***datafile***).

Vamos a configurarlo en nuestra PDB.

Lo primero que debemos crear es definir el tablespace “**shadow tablespace“** antes de activarlo, porque si lo hacemos al revés, primero activar y después crear, recibiremos el siguiente error:

```sql
SQL> ALTER PLUGGABLE DATABASE ENABLE LOST WRITE PROTECTION;
ALTER PLUGGABLE DATABASE ENABLE LOST WRITE PROTECTION
*
ERROR at line 1:
ORA-65491: A lost write bigfile tablespace must exist before attempting to enable lost write.
Help: https://docs.oracle.com/error-help/db/ora-65491/
```

Vamos a crear primero *STTab001*:

```sql
SQL> CREATE BIGFILE TABLESPACE STTab001 DATAFILE SIZE 10M LOST WRITE PROTECTION;

Tablespace created.
```

Una vez creado, procedemos activarlo en nuestra PDB:

```sql
SQL> r
  1* select PROPERTY_NAME, PROPERTY_VALUE from database_properties where PROPERTY_NAME='NEW_LOST_WRITE'

no rows selected

SQL>  ALTER PLUGGABLE DATABASE ENABLE LOST WRITE PROTECTION;

Pluggable database altered.

SQL> r
  1* select PROPERTY_NAME, PROPERTY_VALUE from database_properties where PROPERTY_NAME='NEW_LOST_WRITE'

PROPERTY_NAME        PROPERTY_VALUE
-------------------- --------------------
NEW_LOST_WRITE       TRUE
```

Si nosotros lo hubiéramos intentado habilitar desde **CDB$Root** para que aplique a todas las PDB, hubiéramos recibido el siguiente error:

```sql
SQL> alter session set container=cdb$root;

Session altered.

SQL> CREATE BIGFILE TABLESPACE STTab001 DATAFILE SIZE 10M LOST WRITE PROTECTION;

Tablespace created.

SQL> ALTER PLUGGABLE DATABASE ENABLE LOST WRITE PROTECTION;
ALTER PLUGGABLE DATABASE ENABLE LOST WRITE PROTECTION
*
ERROR at line 1:
ORA-65046: operation not allowed from outside a pluggable database
Help: https://docs.oracle.com/error-help/db/ora-65046/
```

Definimos ambos tablespaces:

```sql
SQL> CREATE BIGFILE   TABLESPACE Tab002 DATAFILE SIZE 10M;
Tablespace created.

SQL> CREATE SMALLFILE TABLESPACE SmallTab001 DATAFILE SIZE 1M ;
Tablespace created.

SQL> ALTER TABLESPACE SmallTab001 ADD DATAFILE SIZE 1M: 
Tablespace altered.
```

Verificamos el paso previo:

```sql
SQL> r
  Select tablespace_name, contents, lost_write_protect from dba_tablespaces

TABLESPACE_NAME                CONTENTS              LOST_WR
------------------------------ --------------------- -------
SYSTEM                         PERMANENT             OFF
SYSAUX                         PERMANENT             OFF
UNDOTBS1                       UNDO                  OFF
TEMP                           TEMPORARY             OFF
USERS                          PERMANENT             OFF
STTAB001                       LOST WRITE PROTECTION OFF
TAB002                         PERMANENT             OFF
SMALLTAB001                    PERMANENT             OFF

SQL> r
  1   Select Tablespace_Name,LOST_WRITE_PROTECT ,File_Name, File_Id
  2     From Dba_Data_Files
  3    Where Tablespace_Name in ('STTAB001','TAB002','SMALLTAB001')
  4*  order by file_id

TABLESPACE_NAME                LOST_WR FILE_NAME                                                                                               FILE_ID
------------------------------ ------- ---------------------------------------------------------------------------------------------------- ----------
STTAB001                       OFF     +DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/sttab001.280.1213616675                       13
TAB002                         OFF     +DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/tab002.281.1213625663                         14
SMALLTAB001                    OFF     +DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/smalltab001.282.1213625677                    15
SMALLTAB001                    OFF     +DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/smalltab001.283.1213625699                    16
```

Habilitamos la protección de datos a dos niveles:

* A nivel de tablespace *TAB002*
    
* A nivel d*e* datafiles de *SMALLTAB001*.
    

```sql
SQL> ALTER TABLESPACE TAB002 ENABLE LOST WRITE PROTECTION;

Tablespace altered.

SQL> ALTER DATABASE DATAFILE '+DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/smalltab001.283.1213625699' ENABLE LOST WRITE PROTECTION;

Database altered.
```

Verificamos de nuevo que la protección la tenemos activa en ambos tablespace:

```sql
SQL> Select tablespace_name, contents, lost_write_protect from dba_tablespaces;

TABLESPACE_NAME                CONTENTS              LOST_WR
------------------------------ --------------------- -------
SYSTEM                         PERMANENT             OFF
SYSAUX                         PERMANENT             OFF
UNDOTBS1                       UNDO                  OFF
TEMP                           TEMPORARY             OFF
USERS                          PERMANENT             OFF
STTAB001                       LOST WRITE PROTECTION OFF
TAB002                         PERMANENT             ENABLED
SMALLTAB001                    PERMANENT             OFF

8 rows selected.

SQL> r
  1   Select Tablespace_Name,LOST_WRITE_PROTECT ,File_Name, File_Id
  2     From Dba_Data_Files
  3    Where Tablespace_Name in ('STTAB001','TAB002','SMALLTAB001')
  4*  order by file_id

TABLESPACE_NAME                LOST_WR FILE_NAME                                                                                               FILE_ID
------------------------------ ------- ---------------------------------------------------------------------------------------------------- ----------
STTAB001                       OFF     +DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/sttab001.280.1213616675                       13
TAB002                         ENABLED +DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/tab002.281.1213625663                         14
SMALLTAB001                    OFF     +DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/smalltab001.282.1213625677                    15
SMALLTAB001                    ENABLED +DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/smalltab001.283.1213625699                    16
```

Como veis es muy sencillo activarlo.

Para desactivarlo, sería de la siguiente manera:

```sql
SQL> ALTER TABLESPACE TAB002 REMOVE LOST WRITE PROTECTION;

Tablespace altered.

SQL> ALTER PLUGGABLE DATABASE DATAFILE '+DATA/DB23AI_FWX_MAD/4004456EB4523134E0634C00000AA230/DATAFILE/smalltab001.283.1213625699' SUSPEND LOST WRITE PROTECTION;

Pluggable database altered.

SQL> ALTER PLUGGABLE DATABASE DISABLE LOST WRITE PROTECTION;

Pluggable database altered.

SQL> DROP TABLESPACE STTAB001 INCLUDING CONTENTS AND DATAFILES;

Tablespace dropped.
```

Espero que os sirva :)
