domingo, 2 de agosto de 2026

La respuesta: Que impacto tiene el que generemos un Datapump utilizando un método de encriptación por ejemplo nativo o externo, a la hora de comprimir el archivo con el respaldo respectivo.?

 


Nos quedamos en el posteo anterior con la incógnita, o quizás no - porque podría ser que ya lo sabías -, sobre que sucede cuando agregamos algunos pequeños cambios, en la forma en que hacemos respaldos con la utilidad Datapump en la base de datos Oracle.

Prácticamente todos los marcos de auditoría modernos establecen que la información almacenada en medios de respaldo debe protegerse mediante controles criptográficos cuando contiene datos sensibles. En una auditoría, la ausencia de cifrado en los respaldos suele convertirse en un hallazgo de riesgo alto.

Las principales normas y regulaciones que tenemos de referencia para temas de proteción de respaldos son:

1. ISO/IEC 27001:2022 (la más utilizada)

ISO 27001 es el estándar internacional de referencia para Sistemas de Gestión de Seguridad de la Información.

Los controles relacionados son:

Control 8.24 - Use of Cryptography

Establece que la organización debe definir e implementar el uso apropiado de mecanismos criptográficos para proteger la confidencialidad e integridad de la información.

Un respaldo es precisamente información almacenada.

Control 8.13 - Information Backup

Indica que los respaldos deben realizarse, protegerse y probarse periódicamente.

La combinación de ambos controles implica que si el respaldo contiene información sensible, debe protegerse mediante mecanismos adecuados, entre ellos el cifrado.

2. ISO/IEC 27002

Es la guía de implementación de ISO 27001.

Es todavía más explícita.
Indica que los respaldos deben protegerse contra:

  • acceso no autorizado
  • pérdida
  • modificación
  • divulgación

La recomendación práctica es utilizar cifrado cuando el medio pueda salir del control de la organización.

3. PCI DSS 4.0

Es probablemente la norma más estricta para organizaciones que procesan tarjetas de crédito.
Requisitos relevantes:

Requisito 3
Protección de datos del titular de la tarjeta.

Incluye:

  • bases de datos
  • exportaciones
  • respaldos
  • cintas
  • archivos
Todos deben protegerse mediante criptografía fuerte.

Requisito 3.5
Las claves criptográficas deben administrarse correctamente.

Requisito 3.6
Debe existir gestión formal del ciclo de vida de las llaves.
Si un Data Pump contiene información de tarjetas, debe estar cifrado.

4. NIST SP 800-53 Rev. 5

Muy utilizado por agencias gubernamentales y empresas grandes.
Controles relevantes:
CP-9
System Backup
Los respaldos deben protegerse contra divulgación.

SC-28
Protection of Information at Rest
Toda información almacenada debe protegerse.

La guía recomienda explícitamente el uso de cifrado.

MP-4
Media Storage
Los medios de almacenamiento deben protegerse físicamente y mediante mecanismos criptográficos.


5. CIS Controls v8

Los CIS Controls indican:
Control 3
Data Protection
Incluye proteger la información tanto en tránsito como almacenada.
Los respaldos son considerados datos almacenados.

6. COBIT 2019

COBIT no exige AES256 específicamente.
Pero sí establece:
  • protección de activos de información
  • controles de seguridad
  • gestión del riesgo
  • continuidad del negocio
Durante una auditoría COBIT normalmente se preguntará: ¿Cómo protege la organización los respaldos que contienen información sensible?

Y muchas más. Ya con más de 35 años en el ambiente y muchos de ellos involucrados en instituciones reguladas por distintos entes, en donde las auditorias son el pan nuestro de cada año. Y no habló de 1 o 2, por lo general, hay que enfrentar hasta 4 auditorías anuales.

Así que el tema de encriptación y respaldo de información es un tema sensible para la organización y fundamental para los procesos de gestión de respaldos para el departamento de TI.

Y ahora si, podemos empezar a responder concretamente nuestra pregunta: Que impacto tiene el que generemos un Datapump utilizando un método de encriptación por ejemplo nativo o externo, a la hora de comprimir el archivo con el respaldo respectivo.?

Volviendo sobre la imágen al inicio de la entrega, tenemos 2 respaldos realizados en distintas fechas, con prácticamente el mismo tamaño.

Sin embargo, si compactamos el archivo de respaldo con la utilidad GZIP, tenemos como resultado, que uno de los archivos queda en 6.5Gb aproximadamente y el otro en poco más de 80Gb.

Que de especial tiene el archivo generado con la fecha del 31 de Julio de este año en el nombre.?

Si continuas revisando la información que te adjunto, vas a darte cuenta, que básicamente he cambiado la línea de comando de ejecución del respaldo con Datapump, agregando 3 parámetros relacionados con temas de encriptación.

El encryption=ALL, que produce que tanto la metadata como los datos sean encriptados en el momento de ejecución del respaldo.

El encryption_algorithm=AES256 para determinar el tipo de algoritmo a utilizar en la encriptación del archivo y finalmente el encryption_password para ingresar la contraseña utilizada para poder acceder al archivo encriptado.

Este método protegue al archivo resultante de un proceso de exportación de datos o metadata de la base de datos, de que cualquier uso indebido sin autorización que se desee hacer del archivo de respaldo, no pueda llevarse a cabo fácilmente. De facto, los respaldos generados con Datapump, no son protegidos por ningún mecanismo.

Que relación tiene entonces el tamaño del archivo comprimido con el uso de estos parámetros.?

Lo que pasa, es que cuando un archivo es encriptado en la fuente, o sea cuando se esta ejecutando el datapump, el archivo obtenido, pierde capacidad de compresión a la hora de comprimirse con un utilitario externo. 

Porqué pasa esto?

Esta es una excelente pregunta y, de hecho, está directamente relacionada con los principios de la teoría de la información desarrollada por Claude Shannon. El comportamiento que observamos, no es una limitación de Oracle Data Pump, sino una consecuencia natural de cómo funcionan los algoritmos de compresión y cifrado.

¿Cómo funciona gzip?

gzip (basado en DEFLATE, que combina LZ77 y Huffman) busca patrones repetitivos dentro de los datos.

Por ejemplo, si un archivo contiene:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

gzip no almacena las 30 letras "A". Almacena algo equivalente a:

"A" repetida 30 veces

Lo mismo ocurre con:

  • nombres de columnas repetidos
  • bloques de ceros
  • espacios en blanco
  • cadenas repetidas
  • registros similares
  • páginas parcialmente vacías
Precisamente un archivo .dmp de Data Pump contiene muchos de estos patrones, por lo que suele comprimirse muy bien.

¿Qué hace el cifrado AES?

Cuando Oracle utiliza ENCRYPTION=ALL cada bloque del archivo se cifra mediante AES.

Un buen algoritmo criptográfico tiene una propiedad fundamental: El texto cifrado debe ser indistinguible de una secuencia aleatoria.

Por ejemplo, si el archivo original contiene:

CLIENTE
CLIENTE
CLIENTE
CLIENTE
CLIENTE

Después del cifrado podría verse conceptualmente así:

8FA34C1E...
B92D7114...
5C88AF0D...
A13E74F2...
9E0BC813...
Ya no existe ninguna repetición visible.

¿Por qué gzip deja de funcionar?

Porque ya no hay patrones que comprimir.

Desde la perspectiva de gzip, el archivo parece una secuencia completamente aleatoria:

010110101011101010010001011...

Y una secuencia verdaderamente aleatoria no es compresible.

De hecho, si existiera un algoritmo capaz de comprimir significativamente datos cifrados sin conocer la clave, eso implicaría que aún existen patrones detectables, lo cual sería una señal de debilidad del algoritmo criptográfico.

Data Pump sin cifrado

Supongamos un dump de:

100 GB

Puede contener muchas repeticiones.

100 GB
     │
     ▼
gzip
     │
     ▼
25 GB
Reducción del 75%.

Data Pump cifrado
100 GB
     │
     ▼
AES256
     │
     ▼
100 GB de datos pseudoaleatorios
     │
     ▼
gzip
     │
     ▼
99.9 GB
En ocasiones incluso obtendrás: 100.1 GB porque gzip añade sus propias cabeceras y metadatos.

¿Qué hace Oracle cuando se usa COMPRESSION?

Aquí está la diferencia importante.

Cuando ejecutas:

COMPRESSION=ALL
ENCRYPTION=ALL

Oracle no cifra primero.

Internamente realiza algo conceptualmente equivalente a:

Datos Oracle
      │
      ▼
Compresión Data Pump
      │
      ▼
Archivo comprimido
      │
      ▼
AES256
      │
      ▼
Dump cifrado

Es decir:

Primero comprime. Luego cifra.

Por eso la compresión sigue siendo efectiva.

¿Por qué Oracle no cifra primero?

Porque ocurriría exactamente lo que observamos previamente.

Si Oracle hiciera:

Datos
   │
   ▼
AES
   │
   ▼
Compresión

La compresión sería prácticamente inútil.

"Existe un principio ampliamente aceptado en criptografía: un texto cifrado de buena calidad debe tener una entropía cercana al máximo, es decir, parecer completamente aleatorio."

Los algoritmos de compresión funcionan precisamente explotando la reducción de entropía (patrones y redundancias). Por eso ambos procesos son, en cierto modo, opuestos: la compresión elimina redundancias y el cifrado elimina la información aprovechable por un compresor. Una vez que un archivo ha sido correctamente cifrado, ya no debería existir una forma significativa de comprimirlo sin conocer la clave criptográfica.

Entonces, toda esta historia para poder concluir, que la diferencia en el tamaño de compresión va a depender mucho del momento en que hagamos la encriptación.

Los posibles escenarios:
  1. Si la encriptación la hacemos después de haber creado nuestro respaldo sin encriptar de manera nativa, vamos a obtener un buen porcentaje de compresión, pero la información estaría expuesta algunos minutos mientras hacemos el proceso de compresión, para luego encriptar manualmente.
  2. Si usamos la manera nativa de encriptación en el momento de crear el respaldo, pero sin compresión de datos o metadata, la capacidad de comprensión va a ser cercana a "0" o menos de "0" con una herramienta externa o bien, simplemente no se va a comprimir, lo positivo será que el tiempo de ejecución no se ve alterado significativamente y no va a existir exposición de información confidencial nunca.
  3. Si además de encriptar en el momento de ejecutar el respaldo, utilizamos el parámetro de compression COMPRESSION=ALL, el archivo de respaldo tendrá el aproximadamente un poco más del doble del tamaño de un archivo no encriptado comprimido con GZIP -exactamente un 125% más-, y la duración del respaldo, pasa de 25 minutos a 41 minutos, un 64% más.
Según la necesidad que ustedes tengan; el nivel de "apriete" en el cuello que la auditoría este realizando y la disponibilidad de recursos en los ambientes que deben ser respaldos, tanto a nivel de CPU, memoria y almacenamiento, mi recomendación sería:
  1. Para organizaciones que no tienen el tema regulatorio como prioridad, utilizar el método 1.
  2. Para organizaciones que el tema regulatorio no es opcional, pero no cuentan con suficiente recursos de almacenamiento para retención de históricos, utilizar el método 3.
  3. Para organizaciones que están en el medio de las 2 anteriores, usar el método 2.
Recuerden; si no van a encriptar con un método externo en la fuente o como hemos hablado nativamente en el momento de hacer el export con datapump, no encripten antes de hacer la compresión del archivo. Esta debe hacerse una vez que el archivo este comprimido.

[oracle@bd-dev-laboratorio datapump]$ cd validar/
[oracle@bd-dev-laboratorio validar]$ ls -alt
total 157741313
drwxr-xr-x. 4 oracle oinstall          45 Jul 31 23:18 ..
drwxr-xr-x. 2 oracle oinstall           4 Jul 31 22:03 .
-rw-r-----. 1 oracle oinstall 80817483776 Jul 31 17:16 PDB1DEV_3107261650.dmp
-rw-r--r--. 1 oracle oinstall      127544 Jul 31 17:16 PDB1DEV_3107261650.log
-rw-r-----. 1 oracle oinstall 80707993600 Jul 26 22:25 PDB1DEV_2607262200.dmp
-rw-r--r--. 1 oracle oinstall      127393 Jul 26 22:25 PDB1DEV_2607262200.log
[oracle@bd-dev-laboratorio validar]$ gzip2
=== Inicio de compresión: Fri Jul 31 23:38:29 CST 2026 ===
=== Fin de compresión: Sat Aug  1 00:22:45 CST 2026 ===
[oracle@bd-dev-laboratorio validar]$
[oracle@bd-dev-laboratorio validar]$ ls -lat
total 85266481
drwxr-xr-x. 2 oracle oinstall           4 Aug  1 00:22 .
drwxr-xr-x. 4 oracle oinstall          45 Jul 31 23:18 ..
-rw-r-----. 1 oracle oinstall 80826147081 Jul 31 17:16 PDB1DEV_3107261650.dmp.gz
-rw-r--r--. 1 oracle oinstall       17205 Jul 31 17:16 PDB1DEV_3107261650.log.gz
-rw-r-----. 1 oracle oinstall  6486334242 Jul 26 22:25 PDB1DEV_2607262200.dmp.gz
-rw-r--r--. 1 oracle oinstall       17138 Jul 26 22:25 PDB1DEV_2607262200.log.gz
[oracle@bd-dev-laboratorio validar]$

[oracle@bd-dev-laboratorio validar]$ cat /home/oracle/scripts/resp_datapump_PDB1dev.sh
#!/bin/bash
TERM=xterm
USER=oracle
ORACLE_SID=cdb
ORACLE_BASE=/opt/app/oracle
MAIL=/var/spool/mail/oracle
LANG=en_US.UTF-8
HOME=/home/oracle
LOGNAME=oracle
LESSOPEN=||/usr/bin/lesspipe.sh %s
ORACLE_HOME=/opt/app/oracle/product/19.10
PATH=$ORACLE_HOME/bin:$PATH
export ORACLE_HOME ORACLE_BASE ORACLE_SID PATH

EXPDMP=`date '+PDB1DEV_%d%m%y%H%M'`
export EXPDMP

# Script de ejecución sin compresión de respaldos
# expdp c##exportdp/oracle@PDB1dev LOGFILE=$EXPDMP'.log' \
DIRECTORY=EXPDIR DUMPFILE=$EXPDMP EXCLUDE=statistics FULL=YES

# Script de ejecución con compresión de respaldos
expdp c##exportdp/oracle@PDB1dev LOGFILE=$EXPDMP'.log' DIRECTORY=EXPDIR DUMPFILE=$EXPDMP \
EXCLUDE=statistics FULL=YES encryption=ALL encryption_algorithm=AES256 \
encryption_password=NA********************$2026

gzip /respaldos/172.X.X.X/datapump/$EXPDMP*
mv /respaldos/172.X.X.X/datapump/$EXPDMP* /NFS/172.X.X.X/datapump/

[oracle@bd-dev-laboratorio validar]$ /home/oracle/scripts/resp_datapump_PDB1dev.sh


[oracle@bd-dev-laboratoriovalidar]$ tail -n 5 *.log
==> PDB1DEV_0108261124.log <==
Master table "C##EXPORTDP"."SYS_EXPORT_FULL_02" successfully loaded/unloaded
******************************************************************************
Dump file set for C##EXPORTDP.SYS_EXPORT_FULL_02 is:
  /respaldos/172.24.140.99/datapump/PDB1DEV_0108261124.dmp
Job "C##EXPORTDP"."SYS_EXPORT_FULL_02" successfully completed at 
Sat Aug 1 11:46:01 2026 elapsed 0 00:21:57

==> PDB1DEV_2607262200.log <==
Master table "C##EXPORTDP"."SYS_EXPORT_FULL_02" successfully loaded/unloaded
******************************************************************************
Dump file set for C##EXPORTDP.SYS_EXPORT_FULL_02 is:
  /respaldos/172.XX.X.X/datapump/PDB1DEV_2607262200.dmp
Job "C##EXPORTDP"."SYS_EXPORT_FULL_02" successfully completed at 
Sun Jul 26 22:25:29 2026 elapsed 0 00:25:26

==> PDB1DEV_3107261650.log <==
Master table "C##EXPORTDP"."SYS_EXPORT_FULL_02" successfully loaded/unloaded
******************************************************************************
Dump file set for C##EXPORTDP.SYS_EXPORT_FULL_02 is:
  /respaldos/172.X.X.X/datapump/PDB1DEV_3107261650.dmp
Job "C##EXPORTDP"."SYS_EXPORT_FULL_02" successfully completed at 
Fri Jul 31 17:16:28 2026 elapsed 0 00:25:31
[oracle@bd-dev-laboratorio validar]$


[oracle@bd-dev-laboratorio validar]$ ls -lat
total 243147137
-rw-r--r--. 1 oracle oinstall 80832880672 Aug  1 12:49 PDB1DEV_0108261124.dmp.enc
drwxr-xr-x. 2 oracle oinstall           7 Aug  1 12:32 .
drwxr-xr-x. 4 oracle oinstall          45 Aug  1 12:12 ..
-rw-r-----. 1 oracle oinstall 80832880640 Aug  1 11:46 PDB1DEV_0108261124.dmp
-rw-r--r--. 1 oracle oinstall      127549 Aug  1 11:46 PDB1DEV_0108261124.log
-rw-r-----. 1 oracle oinstall 80826147081 Jul 31 17:16 PDB1DEV_3107261650.dmp.gz
-rw-r--r--. 1 oracle oinstall      127544 Jul 31 17:16 PDB1DEV_3107261650.log
-rw-r-----. 1 oracle oinstall  6486334242 Jul 26 22:25 PDB1DEV_2607262200.dmp.gz
-rw-r--r--. 1 oracle oinstall      127393 Jul 26 22:25 PDB1DEV_2607262200.log

[oracle@bd-dev-laboratoriovalidar]$ time openssl enc -aes-256-cbc -pbkdf2 -salt \
-in PDB1DEV_0108261124.dmp -out PDB1DEV_0108261124.dmp.enc
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:

real    17m10.146s
user    1m49.553s
sys     2m16.912s

Durante aproximadamente 13 minutos, el proceso estuvo esperando principalmente operaciones 
de entrada/salida. Además, openssl enc procesa este cifrado como un único flujo; 
asignarle más CPU o más núcleos no hace que una sola ejecución escale linealmente. 
OpenSSL incluye openssl speed precisamente para medir la capacidad criptográfica del 
equipo y distinguirla del rendimiento del almacenamiento


[oracle@bd-dev-laboratoriovalidar]$ openssl speed -evp aes-256-cbc
Doing aes-256-cbc for 3s on 16 size blocks: 135996407 aes-256-cbc's in 3.00s
Doing aes-256-cbc for 3s on 64 size blocks: 38799610 aes-256-cbc's in 3.00s
Doing aes-256-cbc for 3s on 256 size blocks: 9970455 aes-256-cbc's in 3.00s
Doing aes-256-cbc for 3s on 1024 size blocks: 2519818 aes-256-cbc's in 3.00s
Doing aes-256-cbc for 3s on 8192 size blocks: 315709 aes-256-cbc's in 3.00s
Doing aes-256-cbc for 3s on 16384 size blocks: 157698 aes-256-cbc's in 3.00s
OpenSSL 1.1.1k  FIPS 25 Mar 2021
built on: Mon Feb 23 10:24:46 2026 UTC
options:bn(64,64) md2(char) rc4(8x,int) des(int) aes(partial) idea(int) blowfish(ptr)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -O3 -O2 -g -pipe -Wall 
-Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions 
-fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 
-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables 
-fstack-clash-protection -fcf-protection -Wa,--noexecstack -Wa,--generate-missing-build-notes=yes 
-specs=/usr/lib/rpm/redhat/redhat-hardened-ld -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC 
-DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 
-DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM 
-DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DZLIB -DNDEBUG 
-DPURIFY -DDEVRANDOM="\"/dev/urandom\"" 
-DSYSTEM_CIPHERS_FILE="/etc/crypto-policies/back-ends/openssl.config"

The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
aes-256-cbc     725314.17k   827725.01k   850812.16k   860097.88k   862096.04k   861241.34k
[oracle@bd-dev-laboratoriovalidar]$ grep -m1 -o '\baes\b' /proc/cpuinfo
aes
[oracle@bd-dev-laboratoriovalidar]$

Para calcular la velocidad real:

[oracle@bd-dev-laboratoriovalidar]$ bytes=$(stat -c %s PDB1DEV_0108261124.dmp)
[oracle@bd-dev-laboratoriovalidar]$

Esto permitirá comparar el cifrado contra la velocidad máxima de lectura 
y escritura del almacenamiento.

[oracle@bd-dev-laboratoriovalidar]$ awk -v b="$bytes" -v s=1030.146 \
> 'BEGIN {
>     printf "Velocidad promedio: %.2f MiB/s\n", b/s/1024/1024
> }'
Velocidad promedio: 74.83 MiB/s

[oracle@bd-dev-laboratoriovalidar]$ ls -lat
total 91605377
drwxr-xr-x. 2 oracle oinstall           6 Aug  1 14:23 .
drwxr-xr-x. 4 oracle oinstall          45 Aug  1 12:12 ..
-rw-r-----. 1 oracle oinstall  6489619161 Aug  1 11:46 PDB1DEV_0108261124.dmp.gz
-rw-r--r--. 1 oracle oinstall      127549 Aug  1 11:46 PDB1DEV_0108261124.log
-rw-r-----. 1 oracle oinstall 80826147081 Jul 31 17:16 PDB1DEV_3107261650.dmp.gz
-rw-r--r--. 1 oracle oinstall      127544 Jul 31 17:16 PDB1DEV_3107261650.log
-rw-r-----. 1 oracle oinstall  6486334242 Jul 26 22:25 PDB1DEV_2607262200.dmp.gz
-rw-r--r--. 1 oracle oinstall      127393 Jul 26 22:25 PDB1DEV_2607262200.log

[oracle@bd-dev-laboratorio validar]$ time openssl enc -aes-256-cbc -pbkdf2 -salt \
-in PDB1DEV_0108261124.dmp.gz -out PDB1DEV_0108261124.dmp.enc
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:

real    1m35.347s
user    0m8.641s
sys     0m10.881s


[oracle@bd-dev-laboratorio validar]$ ^C
[oracle@bd-dev-laboratorio validar]$ ls -lat
total 97943937
-rw-r--r--. 1 oracle oinstall  6489619184 Aug  1 14:48PDB1DEV_0108261124.dmp.enc
drwxr-xr-x. 2 oracle oinstall           7 Aug  1 14:46 .
drwxr-xr-x. 4 oracle oinstall          45 Aug  1 12:12 ..
-rw-r-----. 1 oracle oinstall  6489619161 Aug  1 11:46PDB1DEV_0108261124.dmp.gz
-rw-r--r--. 1 oracle oinstall      127549 Aug  1 11:46PDB1DEV_0108261124.log
-rw-r-----. 1 oracle oinstall 80826147081 Jul 31 17:16PDB1DEV_3107261650.dmp.gz
-rw-r--r--. 1 oracle oinstall      127544 Jul 31 17:16PDB1DEV_3107261650.log
-rw-r-----. 1 oracle oinstall  6486334242 Jul 26 22:25PDB1DEV_2607262200.dmp.gz
-rw-r--r--. 1 oracle oinstall      127393 Jul 26 22:25PDB1DEV_2607262200.log


expdp c##exportdp/oracle@PDB1dev LOGFILE=$EXPDMP'.log' DIRECTORY=EXPDIR \
DUMPFILE=$EXPDMP EXCLUDE=statistics FULL=YES COMPRESSION=ALL encryption=ALL \
encryption_algorithm=AES256 encryption_password=NA****************2026
Master table "C##EXPORTDP"."SYS_EXPORT_FULL_02" successfully loaded/unloaded ****************************************************************************** Dump file set for C##EXPORTDP.SYS_EXPORT_FULL_02 is: /respaldos/172.x.x.x/datapump/PDB1DEV_0108262144.dmp Job "C##EXPORTDP"."SYS_EXPORT_FULL_02" successfully completed at
Sat Aug 1 22:26:36 2026 elapsed 0 00:41:49

drwxr-xr-x. 4 oracle oinstall 47 Aug 1 22:34 . -rw-r--r--. 1 oracle oinstall 17114 Aug 1 22:26 PDB1DEV_0108262144.log.gz -rw-r-----. 1 oracle oinstall 14740083605 Aug 1 22:26 PDB1DEV_0108262144.dmp.gz drwxr-xr-x. 2 oracle oinstall 7 Aug 1 14:46 validar

sábado, 1 de agosto de 2026

Que impacto tiene el que generemos un Datapump utilizando un método de encriptación por ejemplo nativa o externa, a la hora de comprimir el archivo con el respaldo respectivo.?

 


Hola gente,

Que impacto tiene el que generemos un Datapump utilizando un método de encriptación por ejemplo nativa o externa, a la hora de comprimir el archivo con el respaldo respectivo.?

Te haz puesto a pensar o haz tenido la curiosidad de validarlo.?

Muy pocas veces me han consultado, cuál es la metodología que uso para crear contenido. La pregunta no es difícil de hacer y mucho menos de contestar.

Desde que estaba en primaria y estudiaba el método científico, utilicé esa metodología para aclarar o complicar aún más el escenario, sobre todo en mi vida.

El método científico suele enseñarse en la escuela como una serie de pasos (observar, formular una hipótesis, experimentar, analizar y concluir), pero su mayor valor no está en memorizar esos pasos, sino en la forma de pensar que desarrolla.

Es una herramienta para enfrentarse a la incertidumbre y tomar mejores decisiones.

Algunas de las enseñanzas más importantes que deja desde la educación primaria son:

-Observar antes de concluir.
Enseña a prestar atención a los hechos antes de emitir un juicio. Muchas veces creemos saber la respuesta, pero una observación cuidadosa revela una realidad diferente.

-Hacer preguntas.
La ciencia comienza con una pregunta, no con una respuesta. Desarrollar la curiosidad es una habilidad que sirve toda la vida.

-No aceptar todo como cierto.
Fomenta un sano escepticismo: "¿Cómo lo sabemos?", "¿Qué evidencia existe?". Esto ayuda a distinguir hechos de opiniones o rumores.

-Equivocarse es parte del aprendizaje.
Una hipótesis incorrecta no significa fracaso; significa que se ha aprendido algo. El error deja de verse como un enemigo y se convierte en una fuente de conocimiento.

-Las ideas deben poder comprobarse.
No basta con creer algo o que "parezca lógico". Las afirmaciones importantes deben sustentarse con evidencia.

-Cambiar de opinión cuando aparecen nuevos datos.
Una de las mayores virtudes del pensamiento científico es la disposición a modificar nuestras conclusiones si la evidencia lo justifica.

-Ser paciente y metódico.
Los buenos resultados rara vez aparecen por casualidad. La disciplina y el orden son fundamentales para llegar a conclusiones confiables.

-Diferenciar correlación de causalidad.
Que dos eventos ocurran juntos no significa necesariamente que uno cause al otro. Esta es una lección valiosa incluso para interpretar noticias o estadísticas.

-Documentar el proceso.
Registrar lo que se hizo permite repetir el experimento, verificar resultados y aprender de ellos. En muchas profesiones esto se traduce en procedimientos, auditorías y trazabilidad.

-Aceptar que el conocimiento siempre puede mejorar.
La ciencia no busca verdades absolutas, sino las mejores explicaciones disponibles con la evidencia del momento.

Estas 2 últimas son de especial cuidado, por que me permiten reconstruir una y otra vez, el experimento y obtener mis conclusiones finales.

En el próximo post, te respondo la pregunta que inicialmente hice.

Buen fin de semana para todos y todas.

 


martes, 28 de julio de 2026

El arte de estar distraído en un DBA

 


Hace muchos años, cuando aún las redes sociales, no eran un distractor para todo y apenas se ponía de moda el teléfono celular solo para llamadas y algunos cuantos mensajes SMS, tuve uno de los "lapsus mentalis" más costosos.

Estaba en medio de una depuración de un procedimiento y necesitaba cambiar las características de una tabla, cuando en ese momento sonó el teléfono.

Pude haber ignorado la llamada, pero era de mi casa, así que procedí a contestar. En ese momento sucedido, sucedido una cadena de acontencimientos que terminaron con el borrado accidental de la tabla de producción y no de la tabla temporal de pruebas.

Ya lo sabía con anticipación, el cerebro humano de los hombres, no tiene la capacidad de multiprocesamiento en línea, pero aún así, lo intenté y me equivoqué.

"La experiencia es una maestra muy cara, pero los necios no aprenden de otra."

Nunca más cuando debí contestar un teléfono, continuaba con las manos en el teclado, la lección fue muy dura y como decimos por acá, "al mejor mono se le cae el zapote" y a veces algo más.

martes, 21 de julio de 2026

Un verdadero clásico: conocías el paquete DBMS_DB_VERSION? Compilación condicional en la base de datos Oracle


Es un paquete pequeño, pero contiene más elementos de los que normalmente se utilizan. Su propósito principal es permitir que el código PL/SQL sea compatible entre distintas versiones de Oracle mediante compilación condicional y comprobaciones de versión.

Este paquete expone constantes que permiten identificar la versión mayor, la release y comprobar características específicas de la base de datos.

Una de las razones por las que existe este paquete es permitir escribir código compatible con varias versiones de Oracle.

El paquete principalmente es llamado a través de sus constantes VERSION y RELEASE, no expone procedimientos, funciones ni parámetros, sino únicamente constantes públicas como:

Además de VERSION y RELEASE, el paquete define constantes booleanas que permiten saber si el código se está compilando para una determinada versión.

En la versión de base de datos Oracle AI Database 26ai, podemos observar en el código, como las constantes para las versiones de base de datos 11.1 hacia atrás han sido marcadas como obsoletas.

Las constantes VER_LEx, son especialmente útiles cuando el objetivo es mantener compatibilidad hacia atrás.

      LINE TEXT
---------- ------------------------------------------------------------------------------
         1 package dbms_db_version is
         2   version constant pls_integer :=
         3           23; -- RDBMS version number
         4   release constant pls_integer := 0;  -- RDBMS release number
         5
         6   /* The following boolean constants follow a naming convention. Each
         7      constant gives a name for a boolean expression. For example,
         8      ver_le_9_1  represents version <=  9 and release <= 1
         9      ver_le_10_2 represents version <= 10 and release <= 2
        10      ver_le_10   represents version <= 10
        11
        12      Code that references these boolean constants (rather than directly
        13      referencing version and release) will benefit from fine grain
        14      invalidation as the version and release values change.
        15
        16      A typical usage of these boolean constants is
        17
        18          $if dbms_db_version.ver_le_10 $then
        19            version 10 and ealier code
        20          $elsif dbms_db_version.ver_le_11 $then
        21            version 11 code
        22          $else
        23            version 12 and later code
        24          $end
        25
        26      This code structure will protect any reference to the code
        27      for version 12. It also prevents the controlling package
        28      constant dbms_db_version.ver_le_11 from being referenced
        29      when the program is compiled under version 10. A similar
        30      observation applies to version 11. This scheme works even
        31      though the static constant ver_le_11 is not defined in
        32      version 10 database because conditional compilation protects
        33      the $elsif from evaluation if the dbms_db_version.ver_le_10 is
        34      TRUE.
        35   */
        36
        37   /* Deprecate boolean constants for unsupported releases */
        38
        39   ver_le_9_1    constant boolean := FALSE;
        40   PRAGMA DEPRECATE(ver_le_9_1);
        41   ver_le_9_2    constant boolean := FALSE;
        42   PRAGMA DEPRECATE(ver_le_9_2);
        43   ver_le_9      constant boolean := FALSE;
        44   PRAGMA DEPRECATE(ver_le_9);
        45   ver_le_10_1   constant boolean := FALSE;
        46   PRAGMA DEPRECATE(ver_le_10_1);
        47   ver_le_10_2   constant boolean := FALSE;
        48   PRAGMA DEPRECATE(ver_le_10_2);
        49   ver_le_10     constant boolean := FALSE;
        50   PRAGMA DEPRECATE(ver_le_10);
        51   ver_le_11_1   constant boolean := FALSE;
        52   PRAGMA DEPRECATE(ver_le_11_1);
        53   ver_le_11_2   constant boolean := FALSE;
        54   ver_le_11     constant boolean := FALSE;
        55   ver_le_12_1   constant boolean := FALSE;
        56   ver_le_12_2   constant boolean := FALSE;
        57   ver_le_12     constant boolean := FALSE;
        58   ver_le_18     constant boolean := FALSE;
        59   ver_le_19     constant boolean := FALSE;
        60   ver_le_20     constant boolean := FALSE;
        61   ver_le_21     constant boolean := FALSE;
        62   ver_le_23     constant boolean := TRUE;
        63
        64 end dbms_db_version;

64 rows selected.

SQL>

Esta es una funcionalidad poco conocida pero que tiene más de 20 años de existencia.



[oracle@oracle-server-26ai ~]$ sqlplus /nolog

SQL*Plus: Release 23.26.2.0.0 - Production on Wed Jul 22 00:12:04 2026
Version 23.26.2.0.0

Copyright (c) 1982, 2026, Oracle.  All rights reserved.

SQL> connect / as sysdba
Connected.
SQL> show pdbs

    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB1                           READ WRITE NO
SQL> alter session set container=pdb1;

Session altered.

PL/SQL procedure successfully completed.

El paquete no devuelve la versión completa de la base de datos, sólo la versión base
SQL> set serveroutput on SQL> begin dbms_output.put_line( dbms_db_version.version ); end; / 23 PL/SQL procedure successfully completed.

Podemos generar una versión de la consulta ampliada para poder mostrar un poco más de
información utilizando la constante RELEASE
SQL> set serveroutput on declare begin dbms_output.put_line('Oracle Version'); dbms_output.put_line('--------------'); dbms_output.put_line( dbms_db_version.version || '.' || dbms_db_version.release ); dbms_output.put_line('Compatible: ' || dbms_db_version.version || '.' || dbms_db_version.release ); end; / Oracle Version -------------- 23.0 Compatible: 23.0
PL/SQL procedure successfully completed.

Compilación condicional
Oracle permite usar directivas especiales:
  • $IF
  • $THEN
  • $ELSE
  • $END

Estas son evaluadas por el compilador.

Por ejemplo:
SQL> DECLARE x number; BEGIN $IF DBMS_DB_VERSION.VERSION >= 23 $THEN x := 10; $ELSE x := 20; $END DBMS_OUTPUT.PUT_LINE('Valor de x: '||x); END; / Valor de x: 10 PL/SQL procedure successfully completed.

En este caso el compilador dependiendo la versión en la cuál compiles el programa,
así será la generación del código que utilice. por eso en la ejecución del procedimiento
en la versión 26.23.2 devuelve el valor 10
Pero si ejecutamos el mismo código en una versión 19c, el resultado será 20.
SQL> select BANNER_FULL from v$version; BANNER_FULL -------------------------------------------------------------------------------- Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.22.0.0.0 SQL> DECLARE x number; BEGIN $IF DBMS_DB_VERSION.VERSION >= 23 $THEN x := 10; $ELSE x := 20; $END DBMS_OUTPUT.PUT_LINE('Valor de x: '||x); END; / Valor de x: 20 PL/SQL procedure successfully completed. Todo esto esta muy bien, pero el procedimiento va más allá.
Podemos utilizar las constantes boleanas, para determinar cuál es la versión de la
base de datos de tal forma que basado en el valor obtenido, ejecute la parte del código
que corresponda.
Ejecutando en Oracle AI Database 26ai.
SQL> DECLARE x NUMBER; BEGIN IF DBMS_DB_VERSION.VER_LE_19 THEN x := 10; ELSIF DBMS_DB_VERSION.VER_LE_23 THEN x := 13; ELSE x := 20; END IF; DBMS_OUTPUT.PUT_LINE('Valor de x: ' || x); END; / Valor de x: 13 PL/SQL procedure successfully completed.

Ahora veamos un ejemplo de ejecución sobre una acción real a nivel de la base de datos.
Necesitamos crear un procedimiento que sea capaz de borrar una tabla, pero que dependiendo
de la versión que sea, utilice el método con el condicionamiento IF EXISTS o simplemente un
DROP TABLE, al no existe la validación, como en versiones 19c o previas. #### Oracle 19c SQL> create table t1( x number, y char); Table created. SQL> desc t1 Name Null? Type ---------------------- -------- ---------- X NUMBER Y CHAR(1)
Al ejecutar el procedimiento con el IF EXISTS en 19c, provoca que el procedimiento genere
un error de ejecución ORA-00933
SQL> set serveroutput on SQL> DECLARE BEGIN EXECUTE IMMEDIATE 'DROP TABLE IF EXISTS t1'; DBMS_OUTPUT.PUT_LINE('Tabla T1 eliminada (si existía).'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); END; / ORA-00933: SQL command not properly ended PL/SQL procedure successfully completed.
Ahora hagamos el mismo proceso, pero con la sintáxis aceptada en 19c.
SQL> DECLARE BEGIN EXECUTE IMMEDIATE 'DROP TABLE t1'; DBMS_OUTPUT.PUT_LINE('Tabla T1 eliminada.'); EXCEPTION WHEN OTHERS THEN IF SQLCODE = -942 THEN DBMS_OUTPUT.PUT_LINE('La tabla T1 no existe.'); ELSE RAISE; END IF; END; / Tabla T1 eliminada. PL/SQL procedure successfully completed. SQL> create table t1( x number, y char); Table created.

Ahora agreguemos la opción de compilación condicional al script, para que no nos genere error
en la versión 19c. DECLARE BEGIN $IF DBMS_DB_VERSION.VERSION >= 23 $THEN EXECUTE IMMEDIATE 'DROP TABLE IF EXISTS t1'; $ELSE BEGIN EXECUTE IMMEDIATE 'DROP TABLE t1'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END; $END DBMS_OUTPUT.PUT_LINE('Proceso finalizado.'); END; / Proceso finalizado. PL/SQL procedure successfully completed. SQL> desc t1 ERROR: ORA-04043: object t1 does not exist SQL>

En la version de Oracle AI Database 26ai, ambas instrucciones serán ejecutadas sin presentar
ningún error, ya que ambas son válidas. ##Oracle 26ai SQL> create table t1( x number, y char); Table created. SQL> DECLARE BEGIN EXECUTE IMMEDIATE 'DROP TABLE t1'; DBMS_OUTPUT.PUT_LINE('Tabla T1 eliminada.'); EXCEPTION WHEN OTHERS THEN IF SQLCODE = -942 THEN DBMS_OUTPUT.PUT_LINE('La tabla T1 no existe.'); ELSE RAISE; END IF; END; / Tabla T1 eliminada. PL/SQL procedure successfully completed.
¿Por qué Oracle diseñó este mecanismo?

Esto lo hizo pensado principalmente para fabricantes de software (ISVs) y equipos que mantienen una misma base de código para múltiples versiones de Oracle. Por ejemplo, un producto que debe soportar Oracle 19c, 21c y 23ai puede distribuir el mismo código fuente y dejar que cada base de datos compile automáticamente la variante adecuada.


El dato histórico interesante:

Aunque el paquete existe desde 9.2, su verdadero protagonismo llegó con PL/SQL Conditional Compilation, introducida en Oracle Database 10g Release 2 (10.2). Fue entonces cuando Oracle empezó a recomendar expresiones como:
$IF DBMS_DB_VERSION.VER_LE_10 $THEN
   -- Código para Oracle 10g o anterior
$ELSIF DBMS_DB_VERSION.VER_LE_11 $THEN
   -- Código para Oracle 11g
$ELSE
   -- Código para versiones posteriores
$END

Antes de 10.2 el paquete ya existía, pero no podía aprovecharse con este mecanismo de compilación condicional, que es precisamente el uso para el que fue diseñado

Esta característica recién ha cumplido 24 años de existencia. La conocías.?


lunes, 13 de julio de 2026

Cuando te contratan para perder.

 

Hace unos días empecé a ver Ted Lasso. Curiosamente, después de una copa de vino, la serie me llevó a pensar en algo que he visto repetirse durante más de treinta años trabajando en tecnología.

No hablo de servidores, bases de datos o proyectos.

Hablo de personas.

Con el tiempo uno descubre que no todas las contrataciones persiguen el mismo objetivo.

Hay empresas que contratan para construir.
Otras contratan para transformar.
Pero también existen aquellas que contratan para encontrar a quién cargarle el peso de un fracaso que comenzó mucho antes de que esa persona llegara.

Es una realidad incómoda.
Muchas veces creemos que nos buscan porque somos la mejor opción para resolver un problema complejo. Nos ilusiona pensar que podremos aportar nuestra experiencia, ordenar el caos y dejar una organización mejor de como la encontramos.

Sin embargo, en algunas ocasiones el desenlace ya estaba decidido.
El presupuesto ya estaba agotado.
La confianza ya estaba rota.
La dirección ya había perdido el rumbo.
Las decisiones importantes ya habían sido tomadas.

Y la contratación no era el comienzo de un rescate, sino el último acto antes del cierre del telón.

No eres el capitán del barco.

Eres el nombre que aparecerá en el informe final.

Durante mi carrera he visto excelentes profesionales fracasar en lugares donde, simplemente, nadie podía tener éxito.

Personas inteligentes, responsables y comprometidas que terminaron cuestionando su capacidad, cuando en realidad habían sido colocadas en un escenario donde el resultado estaba condicionado desde el primer día.

En informática esto ocurre con frecuencia.

Llega un nuevo gerente de TI cuando la empresa lleva años sin invertir.
Contratan un DBA cuando las políticas de respaldo nunca existieron.
Incorporan un arquitecto cuando el sistema acumula veinte años de deuda técnica.

Nombran un líder cuando el equipo perdió la confianza hace mucho tiempo.

Después, cuando nada cambia en unos cuantos meses, la conclusión parece sencilla:
"El nuevo tampoco funcionó."
Pero la pregunta correcta casi nunca es esa.

La pregunta debería ser:
¿Realmente alguien quería que funcionara?

Con los años también entendí que este fenómeno no pertenece únicamente al mundo laboral.
Sucede en las relaciones personales.

Hay personas que llegan intentando reconstruir vínculos que llevan años deteriorándose.
Intentan comunicarse.
Intentan comprender.
Intentan cambiar.

Mientras la otra parte ya tomó la decisión de irse hace mucho tiempo.

No buscan reconstruir.
Buscan confirmar que ya no había nada por hacer.

Y entonces aparece alguien dispuesto a luchar una batalla que ya había terminado antes de comenzar.

La experiencia, sin embargo, también enseña algo esperanzador.

No todos los desafíos imposibles son una trampa.
Algunas de las mejores historias profesionales nacen precisamente de proyectos que parecían condenados.
La diferencia suele estar en algo que pocas veces aparece en una descripción de puesto.

La voluntad real de cambiar.
Cuando existe esa voluntad, incluso con pocos recursos, los equipos encuentran caminos.

Cuando no existe, ni el mejor profesional del mundo puede fabricar compromiso donde nadie quiere asumirlo.

Si pudiera dar un consejo a quienes apenas comienzan su carrera, no sería "acepten todos los retos".

Sería algo distinto.
Aprendan primero a identificar la naturaleza del desafío.
Antes de aceptar un puesto, hagan preguntas difíciles:
  • ¿Por qué se fue la persona anterior?
  • ¿Cuántas personas han ocupado ese cargo en los últimos años?
  • ¿Qué decisiones puede tomar realmente quien ocupe el puesto?
  • ¿Existe presupuesto para cambiar las cosas?
  • ¿La dirección está dispuesta a modificar aquello que provocó el problema?
Las respuestas a esas preguntas suelen revelar mucho más que una entrevista de una hora.

El talento es importante.

Pero también lo es elegir las batallas correctas.

Y para quienes ya acumulamos algunas décadas de experiencia, el aprendizaje quizá sea diferente.

No debemos confundir resiliencia con sacrificio infinito.

No tenemos que demostrar constantemente que podemos salvar cualquier proyecto.

Hay momentos en que la mayor muestra de madurez profesional consiste en reconocer que una organización no busca soluciones.

Busca un responsable.

Y son dos cosas completamente distintas.

Decir "no" también forma parte de la experiencia.

Renunciar antes de convertirnos en el chivo expiatorio de decisiones ajenas también es una forma de proteger nuestra integridad profesional.

No porque tengamos miedo de fracasar.

Sino porque entendimos que no todo fracaso nos pertenece.

Después de tantos años sigo creyendo que las personas pueden cambiar organizaciones.

He visto equipos extraordinarios lograr cosas que parecían imposibles.

Pero también aprendí que ninguna persona, por brillante que sea, puede reemplazar la voluntad colectiva de hacer que las cosas no funcionen.

Hay barcos que todavía pueden repararse.
Y hay barcos que solo buscan un nuevo capitán para explicar por qué terminaron hundiéndose.

La experiencia consiste, precisamente, en aprender a distinguir unos de otros.

Porque, al final, el verdadero éxito profesional no siempre consiste en salvar todos los barcos.

A veces consiste en reconocer cuáles todavía quieren navegar.

No me hagan mucho caso, yo ya estoy un poco viejo y creo que la entrada en años me empieza a pasar factura.

Solo tengan presente una cosa, la vida es corta, mucho más de lo que crees cuando tienes 20, 30 o 40 años. Despues de los 50's, sólo piensas en una cosa: Como tener paz y como vivir bien.

Algunos dirán que con 58 años, aún me queda mucho por hacer. Y si, tienen mucha razón, pero mis prioridades actuales, son muy distintas a las de hace 20 años atrás.

En ocasiones, desearía correr detrás de un balón, saltar y golpearlo como lo hacía cuando tenía 20. Pero la realidad es otra. Mi cuerpo me lo recuerda cada mañana al levantarme y cada día al final. Ya no soy lo mismo y nunca más lo volveré a hacer. Esa es la realidad.

Lo único que nunca deberíamos permitirnos es cargar con la culpa de un fracaso cuya causa nunca estuvo en nuestras manos.

Todos los Sábados a las 8:00PM