Corrupcion de bloques no detectados por validate

Hoy vamos a ver una entada que nos puede traer un poco de cabeza.

Supongamos tenemos la tipica consulta que nos devuelve un error de corrupcion de bloque ORA-01578: ORACLE data block corrupted

SQL> select something from sometable  where file_name='whatever';
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 377, block # 2818432)
ORA-01110: data file 377:
'+DATA/TESTDB/DATAFILE/TESTDB.20221119.110001.377.dbf' 

Ante este error, nuestros pasos suelen ser claros.

  • Buscamos los bloques corruptos con rman validate o en su defecto dbverify dbv
  • Comprobamos la vista V$DATABASE_BLOCK_CORRUPTION;
  • Recuperamos de backup datafile & block recover datafile 377block 2818432;

Pero , que ocurre si tras ejecutar el validate o el dbv ?

Si miramos el alert.log durane la validacion, veremos lineas con el contenido

TESTDB(3):Completely zero block found during validation

Esto nos indica que es un error en un bloque que contiene solo ceros.
Oracle por diseño no escribe bloques con todo ceros, por lo que este error es heredado del sistema operativo o el sistema de almacenamiento.

Para solucionar este problema deberemos de recuperar ese datafile desde un backup con cualquiera de los metodos soportados

Mas informacion como siempre en Oracle Support

  • Physical Corrupted Blocks consisting of all Zeroes indicate a problem with OS, HW or Storage (Doc ID 1545366.1)

Bucle sleep en codigo PL-SQL

Vamos a ver una entrada rapidisima y sencillisima para dummies.

Como introducimos una espera en codigo PL-SQL

La respuesta es sencillisima, con la funcion DBMS_LOCK.SLEEP
Veamos por ejemplo como forzar dos esperas de 1 minuto para obtener un hang analyzer

$ORACLE_HOME/bin/sqlplus -s "/as sysdba" << EOF
oradebug setmypid;
oradebug unlimit;
oradebug hanganalyze 3;
exec dbms_lock.sleep(60);
-- Wait upto 1 minute before getting the second hanganalyze
oradebug hanganalyze 3;
-- Wait upto 1 minute before getting the second hanganalyze
exec dbms_lock.sleep(60);
oradebug hanganalyze 3;
oradebug tracefile_name;
EOF

Uso de variables de entorno en script sde rman

Hoy vamos a ver una entrada muy rapida para dummies.

Muchas veces queremos hacer que el log de rman tenga una variable de entorno ( usualmente a fecha),haciendo algo similar a

#!/bin/bash
HORA=`date +%Y%m%d_%H:%M:%S`
rman  cmdfile restore_${ORACLE_SID}.cmd  log logs/${HORA}_restore_${ORACLE_SID}.log

Pero cuando vamos al subdirecorio de logs nos encontramos con que nos ha creado un fichero llamado ${HORA}_restore_${ORACLE_SID}.log

Como solucionamos esto?

La solucion no pasa por jugar con las comillas sino con el uso del parametro MSGLOG
Simplemente tendremos que cambiar nuestro script por

#!/bin/bash
HORA=`date +%Y%m%d_%H:%M:%S`
rman  cmdfile restore_${ORACLE_SID}.cmd  MSGLOG logs/${HORA}_restore_${ORACLE_SID}.log

Y funcionara tal y como queremos

Errores psdgbt: bind csid (X) does not match session csid (YY)

Hoy vamos a ver una entrada rapida y sencilla que nos ayudara a evitar una cascada de errores en el alert.log

Es posible que, la reiniciar alguna e nuestras bases de datos que se encuentran bajo la monitorizacion de un Enterprise manager veamos que el alert.log de nuestra base de datos comienza a mostrar continuamente errores del tipo

Errors in file /u01/app/oracle/diag/rdbms/TEST_stby/TEST/trace/TEST_ora_743.trc:
Mon March 11 12:24:47 2019
Errors in file /u01/app/oracle/diag/rdbms/TEST_stby/TEST/trace/TEST_ora_743.trc:
Mon March 11 12:25:06 2019
Errors in file /u01/app/oracle/diag/rdbms/TEST_stby/TEST/trace/TEST_ora_743.trc:

Si comprobamos la traza podemos ver como se trata de errores del tipo

psdgbt: bind csid (1) does not match session csid (46)
psdgbt: session charset is XXX

Donde el charset variara en funcion de nuestra base de datos, veamos una de estas trazas

ORACLE_HOME = /u01/app/oracle/product/12.1.0/db
System name: Linux
Node name: test.pamplona.name
Release: 3.8.13-118.19.12.el6uek.x86_64
Version: #2 SMP Tue Oct 31 12:31:15 PDT 2017
Machine: x86_64
Instance name: TEST
Redo thread mounted by this instance: 1
Oracle process number: 32
Unix process pid: 743, image: oracle@test.pamplona.name

*** 2019-03-11 21:20:06.886
*** SESSION ID:(2.57596) 2019-03-11 21:20:06.886
*** CLIENT ID:() 2019-03-11 21:20:06.886
*** SERVICE NAME:() 2019-03-11 21:20:06.886
*** MODULE NAME:(emagent_SQL_oracle_database) 2019-03-11 21:20:06.886
*** CLIENT DRIVER:(jdbcthin) 2019-03-11 21:20:06.886
*** ACTION NAME:(ME$icc_dbs_age_last_backup) 2019-03-11 21:20:06.886

psdgbt: bind csid (1) does not match session csid (46)
psdgbt: session charset is WE8ISO8859P15

*** 2019-03-11 21:20:06.886
dbkedDefDump(): Starting a non-incident diagnostic dump (flags=0x0, level=1, mask=0x0)
—– Error Stack Dump —–
—– Current SQL Statement for this session (sql_id=a0qc12302fzfk) —–
begin dbms_application_info.set_module(:1 , :2 ); end;

La solucion para este problema es muy muy sencila, simplemente, reinicia el agente del enterprise manager del servidor donde se encuentra ubicada la base de datos.

Como siempre, mas informacion en soporte de Oracle
Doc ID 956222.1

Comprobar el estado de una operacion rman

Vamos a volver a las entradas recopilatorias para dummies.

Hoy vamos a ver unas consultas realmente utiles en el uso diario de rman , con ellas, podremos saber cual es el estado de nuestra recuperacion y pode restimar el tiempo que queda.
Lo que vamos ha hacer es comprobar el tiemo que nos indica la propia base de datos en v$session_longops, para ello podemos usar estas dos consultas

--  Tiempo que le queda al rman para recuperar
col OPNAME for a30
select OPNAME,SOFAR/TOTALWORK*100 PCT, 
trunc(TIME_REMAINING/60) MIN_RESTANTES,
trunc(ELAPSED_SECONDS/60) MIN_ATEAGORA
from v$session_longops 
where TOTALWORK>0 and OPNAME like '%RMAN%';

O afinar un poco mas si lo que buscamos son los restores

--estimacion de los restores 
select OPNAME,SOFAR/TOTALWORK*100 PCT,
 trunc(TIME_REMAINING/60) MIN_RESTANTES,
  trunc(ELAPSED_SECONDS/60) MIN_ATEAGORA
  from v$session_longops 
where TOTALWORK>0 and OPNAME like '%RMAN: full datafile restore%';

Otra consulta que nos puede resultar muy util es el saber cuales de nuestros ficheros necesitan recuperacion

-- Info mas detallada de los ficheros y tablespaces de v$recover_file 
COL DF# FORMAT 999
COL DF_NAME FORMAT A70
COL TBSP_NAME FORMAT A15
COL STATUS FORMAT A7
COL ERROR FORMAT A20
COL CHANGE# FORMAT 999999999999999999
SELECT r.FILE# AS df#, d.NAME AS df_name, t.NAME AS tbsp_name,
d.STATUS, r.ERROR, r.CHANGE#, r.TIME
FROM V$RECOVER_FILE r, V$DATAFILE d, V$TABLESPACE t
WHERE t.TS# = d.TS#
AND d.FILE# = r.FILE# ;

Como siempre, podemos encontrar mas informacion en :