ORA-38870: cannot backup a control file that may have incorrect data file structure.

Hoy vamos a volver con una entrada rapida de un problema muy facil de solucionar.

A veces, podemos encnontrarnos en el alert.log con el error

ORA-38870:cannot backup a control file that may have incorrect data file structure

Si miramos las trazas asustan bastante

2018-10-23T16:08:43.542081+02:00
Errors in file /u01/app/oracle/diag/rdbms/test_stby/test/trace/test_m000_425.trc:
ORA-38870: cannot backup a control file that may have incorrect data file structure.
2018-10-23T16:13:43.189251+02:00
Starting control autobackup
********************  WARNING ***************************
The errors during Server autobackup are not fatal, as it
is attempted after sucessful completion of the command.
However, it is recomended to take an RMAN control file
backup as soon as possible because the Autobackup failed
with the following error:
ORA-38870: cannot backup a control file that may have incorrect data file structure.
********************  END OF WARNING *******************

Pero, buscando en la documentacion de Oracle, nos contraremos que

Error code: ORA-38870

Description: cannot backup a control file that may have incorrect data file structure.
This control file was created or converted based on a control file from a time different from the time of the database.
Action: Open database read-only to synchronize the control file with the database dictionary to fix the control file

Cualquier cosa relaccionada con una estructura invalida de un controlfile puede asustar bastante, pero , este alarmante problema se soluciona de manera muy rapida y sencilla, simplemente haciendo eso, abriendo la base de datos en modo lectura.
Y ya no volveremos a ver mas el problema

Comprobando del OEM 13: alertas Data Failure Detected

Hoy vamos a ver otra entrada sobre las comprobaciones del OEM .

Una de los incidentes que hay que limpiar a mano en el enterprise manager es el de la comprobacion de la integridad dela base de datos.
El check de la metrica Data Failure Detected se basa en las comprobaciones de los Health monitor de Oracle.

Como saber a que problema se refiere

Mediante la libreria DBMS_HM podemos acceder a los checks llevados a cabo por Oracle.
Si ejecutamos la consulta

SET LONG 100000;
SET LONGCHUNKSIZE 1000
SET PAGESIZE 1000
SET LINESIZE 512
column name format a20;
column STATUS format a10;
column START_TIME format a20;
column END_TIME format a20;
column name format a20;
column STATUS format a10;
column START_TIME format a30;
column END_TIME format a30;
column CHECK_NAME format a40;

 select run_id,name,check_name,start_time,end_time,status 
   from v$hm_run order by START_TIME asc;

Obtendremos el listado de los checks ejecutados

    RUN_ID NAME                 CHECK_NAME                   START_TIME
---------- ---------------- -------------------- ------------------------------
   1 HM_RUN_1       DB Structure Integrity Check   25-JUL-18 05.18.01.337628 PM
  21 HM_RUN_21      DB Structure Integrity Check   25-JUL-18 05.19.35.157614 PM
  41 HM_RUN_41      DB Structure Integrity Check   25-JUL-18 05.20.51.496617 PM
  61 HM_RUN_61      DB Structure Integrity Check   25-JUL-18 05.52.24.630598 PM
9621 HM_RUN_9621    DB Structure Integrity Check   15-SEP-18 05.51.52.339032 PM
9641 HM_RUN_9641    DB Structure Integrity Check   15-SEP-18 05.53.25.135027 PM
 6 rows selected.

En el caso del ejemplo, preguntaremos por la ultima ejecucion, que es la HM_RUN_9641

DBMS_HM.GET_RUN_REPORT('HM_RUN_9641')
-----------------------------------------------------------------------------------------
Basic Run Information
 Run Name                     : HM_RUN_9641
 Run Id                       : 9641
 Check Name                   : DB Structure Integrity Check
 Mode                         : REACTIVE
 Status                       : COMPLETED
 Start Time                   : 2018-09-15 17:53:25.135027 +02:00
 End Time                     : 2018-09-15 17:53:28.473273 +02:00
 Error Encountered            : 0
 Source Incident Id           : 0
 Number of Incidents Created  : 0

Input Paramters for the Run
Run Findings And Recommendations
 Finding
 Finding Name  : Inaccessible CF
 Finding ID    : 9642
 Type          : FAILURE
 Status        : CLOSED
 Priority      : CRITICAL
 Message       : Control file
               +DATA/test/controlfile/current.599.982430265
               cannot be accessed because of an ASM Failure
 Message       : Database cannot be mounted

Aqui podemos ver como el error es referente a un controlfile inaccesbile , lo que parece ser un error antiguo.

¿Como asegurarnos de que todo esta correcto?

La respuesta mas obia es, lanzar nosotros mismos este check de manera manual para ver el resultado.
Para ello usaremos el procedure DBMS_HM.RUN_CHECK

SQL> SELECT DBMS_HM.GET_RUN_REPORT('Clear_OEM') FROM DUAL;

DBMS_HM.GET_RUN_REPORT('CLEAR_OEM')
-----------------------------------------------------------------------------------
Basic Run Information
 Run Name                     : Clear_OEM
 Run Id                       : 10581
 Check Name                   : DB Structure Integrity Check
 Mode                         : MANUAL
 Status                       : COMPLETED
 Start Time                   : 2018-09-18 20:58:12.283769 +02:00
 End Time                     : 2018-09-18 20:58:12.476010 +02:00
 Error Encountered            : 0
 Source Incident Id           : 0
 Number of Incidents Created  : 0

Input Paramters for the Run
Run Findings And Recommendations

Donde podemos ver como ya no tenemos errores

Como siempre, mas informacion en:

Eliminar un DR del Dataguard

Hoy vamos a ver un a entrada rápida de como eliminamos un DR de una configuración de dataguard.

Tenemos un entorno donde tenemos 2 Physycal standby y queremos eliminar la primera de ellas TEST_STBY1

Comprobemos la configuración de nuestro entorno, nos conectamos a la primaria y ejecutamos:

-bash-4.2$ . oraenv
ORACLE_SID = [oracle] ? TEST
The Oracle base has been set to /opt/app/oracle
-bash-4.2$ export ORACLE_SID=TEST
-bash-4.2$ dgmgrl /

DGMGRL> show configuration verbose;
Configuration - DR_TWO_STANDBY
  Protection Mode: MaxPerformance
  Databases:
    TEST      - Primary database
    TEST_STBY1    - Physical standby database
    TEST_STBY2 - Physical standby database
  Properties:
    FastStartFailoverThreshold      = '30'
    OperationTimeout                = '30'
    FastStartFailoverLagLimit       = '30'
    CommunicationTimeout            = '180'
    FastStartFailoverAutoReinstate  = 'TRUE'
    FastStartFailoverPmyShutdown    = 'TRUE'
    BystandersFollowRoleChange      = 'ALL'
Fast-Start Failover: DISABLED
Configuration Status:
SUCCESS

DGMGRL> show database  'TEST_STBY1';
Database - TEST_STBY1
  Role:            PHYSICAL STANDBY
  Intended State:  APPLY-ON
  Transport Lag:   14 hours 4 minutes 14 seconds
  Apply Lag:       14 hours 4 minutes 14 seconds
  Real Time Query: OFF
  Instance(s):
    TEST
Database Status:
SUCCESS

Tenemos claro que es la que queremos eliminar , de echo, podemos ver como lleva 14 horas. de retraso .
Para eliminarla ejecutaremos el comando Remove Database , si vemos el ejemplo, poderes ver como siempre ponemos el nombre de la base de datos entre comillas simples, en caso de no hacerlo, el dataguard lo tomará como minúsculas


DGMGRL> disable database 'TEST_STBY1';
Disabled.

DGMGRL> remove database 'TEST_STBY1';
Removed database "TEST_STBY1" from the configuration

DGMGRL> show configuration verbose;

Configuration - MyTEST_STBY1
  Protection Mode: MaxPerformance
  Databases:
    TEST      - Primary database
    TEST_STBY2 - Physical standby database
  Properties:
    FastStartFailoverThreshold      = '30'
    OperationTimeout                = '30'
    FastStartFailoverLagLimit       = '30'
    CommunicationTimeout            = '180'
    FastStartFailoverAutoReinstate  = 'TRUE'
    FastStartFailoverPmyShutdown    = 'TRUE'
    BystandersFollowRoleChange      = 'ALL'
Fast-Start Failover: DISABLED
Configuration Status:
SUCCESS

DGMGRL> quit

Ya lo hemos eliminado, pero , deberemos de comprobar en nuestra base de datos primaria que no hemos dejado restos, para ello, buscaremos que los servicios y los destinos de archivado estén limpios de nuestra configuración anterior.

-bash-4.2$ sqlplus "/as sysdba"

SQL> set linesize 800;
SQL> show parameter log_archive_dest_

NAME                                 TYPE        VALUE

log_archive_dest_1                   string      location=USE_DB_RECOVERY_FILE_
                                                 DEST, valid_for=(ALL_LOGFILES,
                                                  ALL_ROLES)
log_archive_dest_2                   string      service="TEST_STBY1", LGWR ASYNC NOAFFIRM
                                             
log_archive_dest_3                   string      service="TEST_STBY2", LGWR ASYNC NOAFFIRM 
												
SQL>   show parameter log_archive_config;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
log_archive_config                   string      dg_config=(TEST,TEST_STBY1,TEST_STBY2)

Podemos ver como el broker no ha limpiado la configuración, por lo que lo haremos nosotros a mano

SQL> alter system set log_archive_dest_2='' scope=both;
SQL> alter system set log_archive_config='dg_config=(TEST,TEST_STBY2)' scope=both;



SQL> show parameter log_archive_config;
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
log_archive_config                   string      dg_config=(TEST,TEST_STBY)
SQL> show parameter log_archive_dest_

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
log_archive_dest_1                   string      location=USE_DB_RECOVERY_FILE_
                                                 DEST, valid_for=(ALL_LOGFILES,
                                                  ALL_ROLES)
log_archive_dest_2                   string
log_archive_dest_3                   string      service="TEST_STBY2", LGWR ASYNC NOAFFIRM
SQL>

Con esto, podremos afirmar que nuestra configuración está limpia

Version del parcheado de la base de datos

Hoy vamos a ver otra de estas entradas para dummies utiles en el dia a dia.
Como sabemos en que version de parcheado nos encontramos?

La primera opcion y mas sencilla es la del uso del binario del sistema operativo opatch, pero , como podemos estar seguros de que el parche/psu se ha ejecutado correctamente y se ha aplicado tambien la parte SQL

Oracle 11g

Si estamos en la version 11g deberemos de hacerlo consultando la tabla del diccionario sys.registry$history

SET LINESIZE 180 PAGESIZE 90 
COLUMN FECHA FORMAT A18
COLUMN action FORMAT A20
COLUMN version FORMAT A10
COLUMN comments FORMAT A30
COLUMN bundle_series FORMAT A10
SELECT TO_CHAR(action_time, 'YYYY-MM-DD HH24:MI') AS FECHA,
       action,
       namespace,
       version,
       comments,
       bundle_series
FROM   sys.registry$history
ORDER by action_time;

Lo que nos devolvera algo similar a :

FECHA              ACTION               NAMESPACE            VERSION    COMMENTS                       BUNDLE_SER
------------------ -------------------- -------------------- ---------- ------------------------------ ----------
07-JAN-2017 15:21  APPLY                SERVER               11.2.0.3   PSU 11.2.0.3.15                PSU
01-DEC-2017 18:59  UPGRADE              SERVER               11.2.0.4.0 Upgraded from 11.2.0.3.0
01-DEC-2017 19:00  APPLY                SERVER               11.2.0.4   PSU 11.2.0.4.171017            PSU

Oracle 12c

Cuando estamos en la version 12c, tendremos dos maneras de encontrar esta informacion:

Preguntando a DBA_REGISTRY_SQLPATCH

La consulta sera muy similar a la anterior, pero en ved de preguntar a el dicionario sys.registry$history, lo haremos a la tabla DBA_REGISTRY_SQLPATCH



SET LINESIZE 180 PAGESIZE 90 
COLUMN FECHA FORMAT A20
COLUMN action FORMAT A10
COLUMN status FORMAT A20
COLUMN description FORMAT A90
COLUMN version FORMAT A10
COLUMN bundle_series FORMAT A10
SELECT TO_CHAR(action_time, 'YYYY-MM-DD HH24:MI:SS') AS action_time,
       action,
       status,
       description,
       version,
       patch_id,
       bundle_series
FROM   sys.dba_registry_sqlpatch
ORDER by action_time;

Lo que nos devolvera algo similar a

ACTION_TIME          ACTION     STATUS     DESCRIPTION                              VERSION      PATCH_ID BUNDLE_SER
-------------------- ---------- ---------- ---------------------------------------- ---------- ---------- ----------
07-MAR-2018 21:37:51 APPLY      SUCCESS    Database Patch Set Update : 12.1.0.2.4  12.1.0.2     20831110 PSU
                                         (20831110)

Mediante el package dbms_qopatch

En la version 12c tenemos el nuevo datapatch en los parcheados, la informacion de los parches de la base de datos esta tambien accesible con el package dbms_qopatch.
Esto ya lo vimos en la entrada Obtener los parches instalados en la base de datos CDB que venia a decir :

 
 set serverout on
exec dbms_qopatch.get_sqlpatch_status;

Lo que nos devuelve

Patch Id : 25171037
        Action : APPLY
        Action Time : 14-JUN-2017 23:09:33
        Description : DATABASE PATCH SET UPDATE 12.1.0.2.170418
        Logfile :
/u01/app/oracle/cfgtoollogs/sqlpatch/25171037/21099266/25171037_apply_SID_2017Jun14_23_09_20.log
        Status : SUCCESS
PL/SQL procedure successfully completed.

Sobre el uso de dbms_qopatch tenemos la URL hay una URL Como saber si un parche esta aplicado en la BBDD que tiene consultas muy utiles para obtener informacion de la base de datos (inventario,paches…)

Esta informacion ha sido obtenido en su totalidad de las URLS:

Restaurando archivelogs

Hoy vamos a volver a las entradas para dummies .
En esta entrada vamos a ver en una entrada muy rapida algunas maneras de restaurar archivelogs.

Desde numero de secuencia

La primera y mas comun recuperar un archiver en conreto

RUN
{
SET ARCHIVELOG DESTINATION TO '/sitiotemporal';
restore archivelog  logseq=8619;
}

Podemos hacerlo tambien con un rango con

restore archivelog from sequence 8619 until sequence 8639;

o tambien con

restore archivelog sequence between 8619 and  8639;

De un dia atras

Esta puede ser muy comoda a la hora de incrementales

RUN
{ 
SET ARCHIVELOG DESTINATION TO '/sitiotemporal';
ALLOCATE CHANNEL d1 DEVICE TYPE disk;
 restore ARCHIVELOG FROM TIME 'SYSDATE-1' UNTIL TIME 'SYSDATE';
}

Tambien podriamos indicarlo

restore ARCHIVELOG FROM TIME "to_date('11/04/18 00:00:01','DD/MM/YY HH24:MI:SS')
UNTIL TIME 'SYSDATE';

En RAC

En un rac es igual que en los anteriores, pero deberemos de indicar el numero de thread que nos corresponde

{
SET ARCHIVELOG DESTINATION TO '/sitiotemporal'
restore archivelog from logseq=8619 until logseq=8632 thread=2;
}