martes, 22 de enero de 2013

ORA-00001: unique constraint (RMAN.TS_U1) violated al realizar resync catalog



El problema se produce al recrear el tablespace temporal y recrearlo, por un bug de Oracle 7215002, que viola la constraint TS_U1 sobre los campos: DBINC_KEY, TS#, DROP_SCN.
 

RMAN> resync catalog;
 
starting full resync of recovery catalog
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03009: failure of resync command on default channel at 01/22/2013 12:04:04
ORA-00001: unique constraint (RMAN.TS_U1) violated

Se puede aplicar el patch correspondiente o realizar el siguiente workarround que lo resuelve de modo inmediato:
1.     Conectarse a la base del catálogo de rman:
SQL> SELECT * from ts where dbinc_key=2 and TS#=2
 
 
DBINC_
KEY
TS#
TS_NAME
CREATE_SCN
CREATE_TIME
BIGFILE
TEMPORARY
DROP_
SCN
DROP_
TIME
INCLUDED_IN_
DATABASE_BACKUP
ENCRYPT_IN_
BACKUP
2
2
TEMPORAL
29087
27/08/2004 16:52:55
NO
NO
 
 
YES
 
2.       Eliminar el tablespace temporal de la table TS:
SQL> delete from ts where dbinc_key=2 and TS#=2;
SQL> COMMIT;
3.     Realizar el resync del catálogo:
RMAN> resync catalog;
 
starting full resync of recovery catalog
full resync complete
 
RMAN>
4.     Verificar que se inserte el registro correspondiente en la tabla TS del catálogo
SQL> SELECT * from ts where dbinc_key=2 and TS#=2
 
DBINC_
KEY
TS#
TS_NAME
CREATE_SCN
CREATE_TIME
BIGFILE
TEMPORARY
DROP_
SCN
DROP_
TIME
INCLUDED_IN_
DATABASE_BACKUP
ENCRYPT_IN_
BACKUP
2
2
TEMPORAL
7121427154
19/01/2013 12:26:42
NO
YES
 
 
NO
 
 

lunes, 3 de septiembre de 2012

ORA-00060 Deadlock detected

    ¿Qué es un deadlock?
Un deadlock o también conocido como abrazo mortal, es una situación que se produce cuando una transacción tiene tomado un recurso, llamémoslo A y requiere un recurso que llamamos B, y a su vez ese recurso B está tomado por otra transacción que requiere el recurso A.

 
La única forma de resolver este problema es que exista algún mecanismo externo que detecte el conflicto y le informe a la transacción que está en esta situación de deadlock, logrando de esta forma que la transacción abandone el intento de obtener ese recurso. Oracle detecta automáticamente los deadlocks realizando un rollback de una de las transacciones, que es la que detectó la situación de deadlock.
En general los deadlocks ocurren por un problema de diseño de la aplicación, por eso es importante poder brindar a las áreas de desarrollo correspondientes, la información necesaria como para que puedan investigar y resolver el problema.
Cuando sucede un deadlock la base de datos registra un error ORA-00060 en el archivo de alertas y se genera un archivo de trace.
A continuación presento un script que utilizo para detectar y enviar por mail los errores de tipo ORA- al cual le incorporé una sección que para el caso de ocurrencia de deadlock, extrae del archivo de trace información útil para que los desarrolladores, puedan resolver el problema.
   Script
 
#
# Funcion: informa sobre errores en el alert de la base de datos a
#          dbas, y a desarrollo envia informacion de deadlocks
# Uso: chk_alert.sh <INSTANCIA> <DIR_ALERT/ALERT>
#
 
DIR=/home/oracle/scripts
 
hora=`date +%H`
if [ $hora -lt 20 ] && [ $hora -gt 09 ]
then
    # Administradores de dia
    USERS="dbdia@mail"
    USERS_DL=desa@mail,dbdia@mail
 
else
    # Administradores de noche
    USERS=dbnoche@mail
    USERS_DL=desa@mail,dbnoche@mail
fi
 
if [ $# -ne 2 ]
then
  echo
  echo " Parametro invalido "
  echo
  echo " Se debe ejecutar chk_alert.sh instancia archivo_alert "
  echo
  exit
else
  file=$2
  instancia=$1
fi
 
#
# Ejecuto el profile de Oracle
#
. /home/oracle/.bash_profile   1>/dev/null 2>/dev/null
export ORACLE_SID=$instancia
 
if ( [ -a $file ] && [ -a $file.chk ] )
then
   ant=`wc -l $file.chk | awk {'print $1'}`
   aho=`wc -l $file | awk {'print $1'}`
  
   if [ $aho -gt $ant ]
   then
      lineas=`expr $aho - $ant `
      tail -$lineas $file | grep ORA- >$DIR/chk_alert.mail
  
      if  [ -s $DIR/chk_alert.mail ]
      then
         mailx -s "Produccion PRD: ALERT ORACLE : $instancia " $USERS <$DIR/chk_alert.mail
  
         if [ `grep ORA-00060 chk_alert.mail | wc -l ` -gt 0 ]
         then
         #                                          
         # Envia mail a desarrollo pues hay deadlock
         #                                          
                nombre_trace="`cat $DIR/chk_alert.mail|grep "ORA-00060"|cut -f8 -d" "|cut -f1 -d.`".trc
 
                n=`cat $nombre_trace|grep -n "Deadlock graph"|tail -1|cut -f1 -d:`
                n=`expr $n + 35`
 
                head -$n $nombre_trace|tail -36>$DIR/deadlock.txt
 
                obj1=`grep "dictionary objn" deadlock.txt|head -1|cut -f2 -d"-"|cut -f1 -d","`
                obj2=`grep "dictionary objn" deadlock.txt|tail -1|cut -f2 -d"-"|cut -f1 -d","`
 
                echo "Objetos Tomados:" >$DIR/chk_deadlock.mail
                echo "================" >>$DIR/chk_deadlock.mail
                sqlplus -S '/ as sysdba' << eof
col object_name format a30
col object_type format a12
spool $DIR/chk_deadlock.lst
select object_name,object_id,object_type from dba_objects where object_id in '$obj1','$obj2');
exit
eof
                cat $DIR/chk_deadlock.lst >>$DIR/chk_deadlock.mail
                echo >>$DIR/chk_deadlock.mail
                echo "Informacion del Deadlock:" >>$DIR/chk_deadlock.mail
                echo "=========================" >>$DIR/chk_deadlock.mail
                cat $DIR/deadlock.txt >>$DIR/chk_deadlock.mail
 
                echo >>$DIR/chk_deadlock.mail
                echo "Archivo Trace:" >>$DIR/chk_deadlock.mail
                echo "==============" >>$DIR/chk_deadlock.mail
                echo $nombre_trace >>$DIR/chk_deadlock.mail
 
                mailx -s "Deadlock en base: $instancia "  $USERS_DL <$DIR/chk_deadlock.mail
 
                cp /dev/null $DIR/deadlock.txt
                cp /dev/null $DIR/chk_deadlock.lst
                cp /dev/null $DIR/chk_deadlock.mail
         fi
         cp /dev/null $DIR/chk_alert.mail
      fi
   fi
fi
cp $file $file.chk
 

Un ejemplo de mail de deadlock detectado por el script de control es el siguiente:

Objetos Tomados:
================

OBJECT_NAME                    OBJECT_ID OBJECT_TYPE
---------------------------- ---------- ------------
SALDOS                         107326      TABLE
MOVIMIENTOS                    107329      TABLE


Informacion del Deadlock:
=========================
Deadlock graph:
---------Blocker(s)-------- ---------Waiter(s)---------
Resource Name process session holds waits process session holds waits
TX-000a0025-00045474 334 171 X 362 823 X
TX-002f0008-0001fbfe 362 823 X 334 171 X
session 171: DID 0001-014E-00003A3F session 823: DID 0001-016A-00004BCF
session 823: DID 0001-016A-00004BCF session 171: DID 0001-014E-00003A3F
Rows waited on:
Session 823: obj - rowid = 0001A341 - AAAaNBAACAABCFDAA9
(dictionary objn - 107329, file - 2, block - 270659, slot - 61)
Session 171: obj - rowid = 0001A33E - AAAaM+AAPAAAGekAAe
(dictionary objn - 107326, file - 15, block - 26532, slot - 30)
Information on the OTHER waiting sessions:
Session 823:
pid=362 serial=33398 audsid=45199005 user: 212/SLU
O/S info: user: aramirez, term: MHWAP006, ospid: 11204:4228, machine: DOMINIO\MHWAP006
program:
Current SQL Statement:
SELECT MAX(AA_EJER) FROM PRE_BEJERCICIO WHERE F_CARGA_ACTO IS NOT NULL AND F_CARGA_ACTO <> NVL(F_PROYECTO,F_CARGA_ACTO+1) AND F_CIERRE IS NULL
End of information on OTHER waiting sessions.
Current SQL statement for this session:
UPDATE CB_SALDOS SET I_SALDO_COMP = I_SALDO_COMP + DECODE(:B4 ,'S',:B2 ,0), I_SALDO_DEV = I_SALDO_DEV + DECODE(:B3 ,'S',:B2 ,0), I_SALDO_PAG = I_SALDO_PAG + DECODE(:B1 ,'S',:B2 ,0) WHERE C_CTAESC = :B6 AND AA_CTAESC = :B5
----- PL/SQL Call Stack -----
object line object
handle number name
0x495892ac0 52 SSS.TG_MOVES_BRIUD
===================================================
PROCESS STATE
-------------
Process global information:
process: 0x4fe689cb8, call: 0x498b0a058, xact: 0x4f623ade0, curses: 0x4fb7b46e8, usrses: 0x4fb7b46e8
----------------------------------------
SO: 0x4fe689cb8, type: 2, owner: (nil), flag: INIT/-/-/0x00
(process) Oracle pid=334, calls cur/top: 0x498b0a058/0x498b57880, flag: (0) -
int error: 0, call error: 0, sess error: 0, txn error 0
(post info) last post received: 0 0 8

Archivo Trace:
==============
/u01/oracle/admin/PRD/udump/prod_ora_1113.trc

 

 

miércoles, 22 de agosto de 2012

ORA-01110 y ORA-01113 al querer abrir la base de datos luego de un corte de energía o shutdown abort


    Luego de un corte de energía, la base de datos daba el siguiente error:

SQL>ALTER DATABASE OPEN
ORA-01113: file 5 needs media recovery
ORA-01110: data file 5: ‘D:\ORACLE\PRODUCT\10.1.0\ORADATA\PROD\DATOS01.DBF’

Revisando el alert.log pude observer que al momento del corte estaba hacienda un backup online, pues la sentencia anterior al startup era un ALTER TABLESPACE … BEGIN BACKUP:

Sat Aug 18 01:05:28 2012
ARC1: Evaluating archive thread 1 sequence 74097
ARC1: Unable to archive thread 1 sequence 74097
      Log actively being archived by another process
Sat Aug 18 01:05:28 2012
Committing creation of archivelog 'D:\ARCHIVED_LOGS\ARCHIVED_PROD\ARCH_PROD_1_74097_611589480.ARC'
Sat Aug 18 01:05:29 2012
ALTER TABLESPACE "DATOS" BEGIN BACKUP
Completed: ALTER TABLESPACE "DATOS" BEGIN BACKUP
Starting up ORACLE RDBMS Version: 10.1.0.5.0.
System parameters with non-default values:
  processes                = 150
  sga_max_size             = 1258291200
  __shared_pool_size       = 620756992
  __large_pool_size        = 8388608
  __java_pool_size         = 8388608
  sga_target               = 1258291200
  control_files            = D:\ORACLE\PRODUCT\10.1.0\ORADATA\PROD\CONTROL01.CTL, D:\ORACLE\PRODUCT\10.1.0\ORADATA\PROD\CONTROL02.CTL, D:\ORACLE\PRODUCT\10.1.0\ORADATA\PROD\CONTROL03.CTL
  db_block_size            = 8192
  __db_cache_size          = 612368384
  compatible               = 10.1.0.5.0
  log_archive_dest_1       = LOCATION=D:\archived_logs\archived_prod\ MANDATORY
  log_archive_format       = arch_prod_%t_%s_%r.arc
  db_file_multiblock_read_count= 16
  db_recovery_file_dest    = D:\oracle\product\10.1.0\flash_recovery_area
  db_recovery_file_dest_size= 2147483648
  undo_management          = AUTO
  undo_tablespace          = UNDOTBS1
  remote_login_passwordfile= EXCLUSIVE
  db_domain                =
  dispatchers              = (PROTOCOL=TCP) SERVICE=orclprodXDB)
  job_queue_processes      = 10
  background_dump_dest     = D:\ORACLE\PRODUCT\10.1.0\ADMIN\PROD\BDUMP
  user_dump_dest           = D:\ORACLE\PRODUCT\10.1.0\ADMIN\PROD\UDUMP
  core_dump_dest           = D:\ORACLE\PRODUCT\10.1.0\ADMIN\PROD\CDUMP
  db_name                  = prod
  open_cursors             = 300
  pga_aggregate_target     = 209715200
Sat Aug 18 08:48:33 2012
starting up 1 dispatcher(s) for network address '(ADDRESS=(PARTIAL=YES)(PROTOCOL=TCP))'...
CJQ0 started with pid=9, OS id=3440
RECO started with pid=8, OS id=3428
Sat Aug 18 08:48:33 2012
starting up 1 shared server(s) ...
PMON started with pid=2, OS id=3332
DBW0 started with pid=4, OS id=3368
LGWR started with pid=5, OS id=3380
CKPT started with pid=6, OS id=3400
MMAN started with pid=3, OS id=3348
Oracle Data Guard is not available in this edition of Oracle.
Sat Aug 18 08:48:35 2012
alter database mount exclusive
Sat Aug 18 08:48:35 2012
Controlfile identified with block size 16384
SMON started with pid=7, OS id=3416
Sat Aug 18 08:48:39 2012
Setting recovery target incarnation to 1
Sat Aug 18 08:48:40 2012
Successful mount of redo thread 1, with mount id 1589792867
Sat Aug 18 08:48:40 2012
Database mounted in Exclusive Mode.
Completed: alter database mount exclusive
Sat Aug 18 08:48:40 2012
alter database open
ORA-1113 signalled during: alter database open...

Lo que hice entonces es hacer un END BACKUP, y luego pudo abrir sin problemas:

SQL> ALTER TABLESPACE DATOS END BACKUP;
Tablespace altered.
SQL > ALTER DATABASE OPEN;
Database altered.
Explicación

El BEGIN BACKUP realizado sobre el tablespace “congela” algunas secciones de los headers de los datafiles, y a partir de ese momento, en redo se genera una marca de comienzo, y se registran las modificaciones. En los datafiles en las secciones de datos también se van registran los cambios. Cuando levantamos la base, parte de ese header se encuentra desactualizado por lo que para Oracle el datafile requiere una recuperación. Al realizarse el END BACKUP esos headers se actualizan, y en los redologs se registra una marca de fin.
Otras formas de solucionar el problema

Asi mismo, se podría hacer también un ALTER DATABASE END BACKUP, lo cual quita de modo backup todos los tablespaces que pudieran habre quedado marcados:
SQL> STARTUP MOUNT
SQL> ALTER DATABASE END BACKUP;

IMPORTANTE: no utilizar end backup si no se esta seguro si los datafiles están actualizados, esto es, si hubo una restauración de algún backup hay que realizar un recover como se indica:

SQL> STARTUP MOUNT
SQL> RECOVER DATABASE;
Referencias