Mostrando las entradas con la etiqueta Oracle. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Oracle. Mostrar todas las entradas

martes, 21 de mayo de 2013

Network Adapter Could not Establish Connection

Este es un escenario curioso: tienes un programa en java que se conecta a una base de datos Oracle usando direcciones IP, pero no se puede conectar a la base de datos aún si usas exactamente la misma cadena de conexión en tnsnames y puedes conectarte a esa base de datos usando el cliente SQL/Plus.

Pero empecemos desde el principio, cuando no tienes ningún problema (porque el nombre del servidor de bases de datos Oracle tiene un nombre de dominio calificado y se puede resolver):

oracle@test:~$ cd $ORACLE_HOME/network/admin
oracle@test:~/app/oracle/product/10.2.0/server/network/admin$ cat tnsnames.ora 
# tnsnames.ora Network Configuration File:

XE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = hera.localdomain)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XE)
    )
  )

XE2 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.108.76)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = SHARED)
      (SERVICE_NAME = XE)
    )
  )

XE3 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.108.76)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XE)
    )
  )

Como puedes ver, hay tres diferentes cadenas de conexión definidas en este archivo tnsnames: una con un FQDN como conexión dedicada, una con una dirección IP como conexión compartida, y la última con una dirección IP como conexión dedicada. Ahora pruebas el nombre del servidor e intentas conectarte usando estos tres servicios:

oracle@test:~$ ping hera
PING hera.localdomain (192.168.108.76) 56(84) bytes of data.
64 bytes from hera.localdomain (192.168.108.76): icmp_req=1 ttl=64 time=8.34 ms
64 bytes from hera.localdomain (192.168.108.76): icmp_req=2 ttl=64 time=3.58 ms

--- hera.localdomain ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
rtt min/avg/max/mdev = 3.589/5.964/8.340/2.376 ms

oracle@test:~$ sqlplus hr/hr@xe

SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 15:44:16 2013

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


Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

oracle@test:~$ sqlplus hr/hr@xe2

SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 15:44:21 2013

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


Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

oracle@test:~$ sqlplus hr/hr@xe3

SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 15:44:26 2013

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


Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

Todo estuvo bien como se esperaba, y aún este diminuto y util programa de prueba de java está trabajando:

oracle@test:~$ cat OracleJdbcExample.java |grep jdbc
        String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.108.76)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XE)))";

oracle@test:~$ javac -g OracleJdbcExample.java 
oracle@test:~$ export CLASSPATH=$CLASSPATH:/usr/lib/oracle/MyJDBC/ojdbc6.jar
oracle@test:~$ java OracleJdbcExample
Current Date from Oracle : 2013-05-15 16:06:08
done

Pero que pasa cuando el nombre del servidor ya no se puede resolver? Como cuando se comentan las líneas de nameserver en /etc/resolv.conf:

oracle@test:/etc# ping hera
ping: unknown host hera

oracle@test:~$ sqlplus hr/hr@xe

SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 16:02:25 2013

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

ERROR:
ORA-12560: TNS:protocol adapter error


Enter user-name: 

oracle@test:~$ sqlplus hr/hr@xe2

SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 16:02:44 2013

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


Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

oracle@test:~$ sqlplus hr/hr@xe3

SQL*Plus: Release 10.2.0.1.0 - Production on Wed May 15 16:02:50 2013

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


Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

SQL> exit
Disconnected from Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

Como se esperaba, la primer cadena de conexión que usa el nombre del servidor no esta funcionando, pero las otras dos que usan direcciones IP aún funcionan. Por lo tanto, el programa de java tiene que funcionar también, correcto?

oracle@test:~$ java OracleJdbcExample
Exception in thread "main" java.sql.SQLRecoverableException: IO Error: Connection reset
 at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:421)
 at oracle.jdbc.driver.PhysicalConnection.(PhysicalConnection.java:531)
 at oracle.jdbc.driver.T4CConnection.(T4CConnection.java:221)
 at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
 at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:503)
 at java.sql.DriverManager.getConnection(DriverManager.java:582)
 at java.sql.DriverManager.getConnection(DriverManager.java:154)
 at OracleJdbcExample.main(OracleJdbcExample.java:25)
Caused by: java.net.SocketException: Connection reset
 at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:96)
 at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
 at oracle.net.ns.DataPacket.send(DataPacket.java:199)
 at oracle.net.ns.NetOutputStream.flush(NetOutputStream.java:211)
 at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:227)
 at oracle.net.ns.NetInputStream.read(NetInputStream.java:175)
 at oracle.net.ns.NetInputStream.read(NetInputStream.java:100)
 at oracle.net.ns.NetInputStream.read(NetInputStream.java:85)
 at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:122)
 at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:78)
 at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1179)
 at oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1155)
 at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:279)
 at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
 at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:366)
 at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:752)
 at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:359)
 ... 7 more

Ese no es el caso. De acuerdo a la nota de Metalink de Oracle 139775.1, cuando tratas de conectarte a un servicio de Oracle por medio de una conexión dedicada usando java, la cadena de conexión tiene direcciones IP en lugar de nombres de dominio calificados, y esas direcciones IP no se pueden resolver en la máquina cliente, obtendrás un mensaje de error Network Adapter Could not Establish Connection, aún si desde ese cliente puedes alcanzar la base de datos usando un cliente SQL/Plus. En este ejemplo el mensaje de error es diferente, supongo que porque estoy usando Oracle 10g XE.

Más información:

Io exception: The Network Adapter could not establish the connection
NL Exception trying to connect to 10g RAC w/JDBC

miércoles, 13 de marzo de 2013

Administrando tareas de mantenimiento en Oracle 11g

Como quizás sepas, si quieres cambiar los parámetros de ejecución de las tareas automáticas de mantenimiento de la base de datos en Oracle 10g, tienes que modificar los trabajos y las ventanas asociadas a esas tareas; por lo tanto, podrías estar tentado a cambiar las tareas de mantenimiento de 11g de la misma forma pero encontrarás que no hay trabajos que parezcan tareas de mantenimiento, y las ventanas aún existen pero están desactivadas:

SQL> set linesize 120
SQL> column WINDOW_NAME format a20
SQL> column ENABLED format a7
SQL> column REPEAT_INTERVAL format a60
SQL> column DURATION format a15
SQL> select window_name, enabled, repeat_interval, duration from dba_scheduler_windows
where window_name like 'WEEK%';

WINDOW_NAME          ENABLED REPEAT_INTERVAL                                              DURATION
-------------------- ------- ------------------------------------------------------------ ---------------
WEEKNIGHT_WINDOW     FALSE   freq=daily;byday=MON,TUE,WED,THU,FRI;byhour=22;byminute=0; b +000 08:00:00
                             ysecond=0

WEEKEND_WINDOW      FALSE    freq=daily;byday=SAT;byhour=0;byminute=0;bysecond=0          +002 00:00:00

Nadie te contó? En Oracle 11g tienes que usar los procedimientos DBMS_AUTO_TASK_ADMIN para controlar las tres tareas de mantenimiento: Automatic Optimizer Statistics Collection, Automatic Segment Advisor y Automatic SQL Tuning Advisor.

Para revisar la información de las tareas puedes hacer esto:

SQL> column CLIENT_NAME format a32
SQL> column STATUS format a10
SQL> column WINDOW_GROUP format a20
SQL> column ATTRIBUTES format a40
SQL> select client_name, status, window_group, attributes from dba_autotask_client;

CLIENT_NAME                      STATUS     WINDOW_GROUP         ATTRIBUTES
-------------------------------- ---------- -------------------- ----------------------------------------
auto optimizer stats collection  ENABLED    ORA$AT_WGRP_OS       ON BY DEFAULT, VOLATILE, SAFE TO KILL
auto space advisor               ENABLED    ORA$AT_WGRP_SA       ON BY DEFAULT, VOLATILE, SAFE TO KILL
sql tuning advisor               ENABLED    ORA$AT_WGRP_SQ       ONCE PER WINDOW, ON BY DEFAULT, VOLATILE
                                                                 , SAFE TO KILL

Como puedes ver, las tres tareas están activadas por defecto y tienen su propio grupo de ventanas, pero todos los grupos de ventanas tienen las mismas ventanas miembros, una por día de la semana:

SQL> select window_name, enabled, repeat_interval, duration from dba_scheduler_windows where window_name in
(select WINDOW_NAME from dba_scheduler_wingroup_members where WINDOW_GROUP_NAME='ORA$AT_WGRP_SQ');

WINDOW_NAME          ENABLED REPEAT_INTERVAL                                              DURATION
-------------------- ------- ------------------------------------------------------------ ---------------
SATURDAY_WINDOW      TRUE    freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0         +000 20:00:00
WEDNESDAY_WINDOW     TRUE    freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0        +000 04:00:00
THURSDAY_WINDOW      TRUE    freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0        +000 04:00:00
SUNDAY_WINDOW        TRUE    freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0         +000 20:00:00
FRIDAY_WINDOW        TRUE    freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0        +000 04:00:00
TUESDAY_WINDOW       TRUE    freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0        +000 04:00:00
MONDAY_WINDOW        TRUE    freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0        +000 04:00:00

7 rows selected.

Entonces, si quieres desactivar una tarea puedes hacerlo de esta forma:

SQL> begin
dbms_auto_task_admin.disable
(client_name => 'sql tuning advisor',
operation    => NULL,
window_name  => NULL);
end;
/

PL/SQL procedure successfully completed.

SQL> select client_name, status, window_group, attributes from dba_autotask_client;

CLIENT_NAME                      STATUS     WINDOW_GROUP         ATTRIBUTES
-------------------------------- ---------- -------------------- ----------------------------------------
auto optimizer stats collection  ENABLED    ORA$AT_WGRP_OS       ON BY DEFAULT, VOLATILE, SAFE TO KILL
auto space advisor               ENABLED    ORA$AT_WGRP_SA       ON BY DEFAULT, VOLATILE, SAFE TO KILL
sql tuning advisor               DISABLED   ORA$AT_WGRP_SQ       ONCE PER WINDOW, ON BY DEFAULT, VOLATILE
                                                                 , SAFE TO KILL

Y para activarla de nuevo:

SQL> begin
dbms_auto_task_admin.enable
(client_name => 'sql tuning advisor',
operation    => NULL,
window_name  => NULL);
end;
/

PL/SQL procedure successfully completed.

SQL> select client_name, status, window_group, attributes from dba_autotask_client;

CLIENT_NAME                      STATUS     WINDOW_GROUP         ATTRIBUTES
-------------------------------- ---------- -------------------- ----------------------------------------
auto optimizer stats collection  ENABLED    ORA$AT_WGRP_OS       ON BY DEFAULT, VOLATILE, SAFE TO KILL
auto space advisor               ENABLED    ORA$AT_WGRP_SA       ON BY DEFAULT, VOLATILE, SAFE TO KILL
sql tuning advisor               ENABLED    ORA$AT_WGRP_SQ       ONCE PER WINDOW, ON BY DEFAULT, VOLATILE
                                                                 , SAFE TO KILL

Ahora, si quieres desactivar una tarea un cierto día (ventana), puedes hacer esto:

SQL> begin
dbms_auto_task_admin.disable
(client_name => 'sql tuning advisor',
operation    => NULL,
window_name  => 'MONDAY_WINDOW');
end;
/

PL/SQL procedure successfully completed.

SQL> select WINDOW_NAME, OPTIMIZER_STATS, SEGMENT_ADVISOR, SQL_TUNE_ADVISOR from dba_autotask_window_clients;

WINDOW_NAME          OPTIMIZER_STATS          SEGMENT_ADVISOR          SQL_TUNE_ADVISOR
-------------------- ------------------------ ------------------------ ------------------------
WEDNESDAY_WINDOW     ENABLED                  ENABLED                  ENABLED
FRIDAY_WINDOW        ENABLED                  ENABLED                  ENABLED
SATURDAY_WINDOW      ENABLED                  ENABLED                  ENABLED
THURSDAY_WINDOW      ENABLED                  ENABLED                  ENABLED
TUESDAY_WINDOW       ENABLED                  ENABLED                  ENABLED
SUNDAY_WINDOW        ENABLED                  ENABLED                  ENABLED
MONDAY_WINDOW        ENABLED                  ENABLED                  DISABLED

7 rows selected.

Y para activar una tarea en una ventana:

SQL> begin
dbms_auto_task_admin.enable
(client_name => 'sql tuning advisor',
operation    => NULL,
window_name  => 'MONDAY_WINDOW');
end;
/

PL/SQL procedure successfully completed.

SQL> select WINDOW_NAME, OPTIMIZER_STATS, SEGMENT_ADVISOR, SQL_TUNE_ADVISOR from dba_autotask_window_clients;

WINDOW_NAME          OPTIMIZER_STATS          SEGMENT_ADVISOR          SQL_TUNE_ADVISOR
-------------------- ------------------------ ------------------------ ------------------------
WEDNESDAY_WINDOW     ENABLED                  ENABLED                  ENABLED
FRIDAY_WINDOW        ENABLED                  ENABLED                  ENABLED
SATURDAY_WINDOW      ENABLED                  ENABLED                  ENABLED
THURSDAY_WINDOW      ENABLED                  ENABLED                  ENABLED
TUESDAY_WINDOW       ENABLED                  ENABLED                  ENABLED
SUNDAY_WINDOW        ENABLED                  ENABLED                  ENABLED
MONDAY_WINDOW        ENABLED                  ENABLED                  ENABLED

7 rows selected.

Finalmente, si quieres cambiar los atributos de una ventana como el intérvalo de repetición, puedes hacerlo como es usual:

SQL> exec dbms_scheduler.set_attribute('MONDAY_WINDOW','repeat_interval','freq=daily;byday=MON;byhour=21;byminute=0; bysecond=0');

PL/SQL procedure successfully completed.

SQL> select window_name, enabled, repeat_interval, duration from dba_scheduler_windows where window_name in
(select WINDOW_NAME from dba_scheduler_wingroup_members where WINDOW_GROUP_NAME='ORA$AT_WGRP_SQ');

WINDOW_NAME          ENABLED REPEAT_INTERVAL                                              DURATION
-------------------- ------- ------------------------------------------------------------ ---------------
SATURDAY_WINDOW      TRUE    freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0         +000 20:00:00
MONDAY_WINDOW        TRUE    freq=daily;byday=MON;byhour=21;byminute=0; bysecond=0        +000 04:00:00
WEDNESDAY_WINDOW     TRUE    freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0        +000 04:00:00
THURSDAY_WINDOW      TRUE    freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0        +000 04:00:00
SUNDAY_WINDOW        TRUE    freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0         +000 20:00:00
FRIDAY_WINDOW        TRUE    freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0        +000 04:00:00
TUESDAY_WINDOW       TRUE    freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0        +000 04:00:00

7 rows selected.

Y en caso de que quieras saber que operación está asociada a que cliente:

SQL> column OPERATION_NAME format a40
SQL> select client_name, operation_name from dba_autotask_operation;

CLIENT_NAME                      OPERATION_NAME
-------------------------------- ----------------------------------------
auto optimizer stats collection  auto optimizer stats job
auto space advisor               auto space advisor job
sql tuning advisor               automatic sql tuning task

Más información:

Managing Automated Database Maintenance Tasks
DBMS_AUTO_TASK_ADMIN

jueves, 7 de marzo de 2013

Arreglando fallas en Oracle 11g con DRA y RMAN

El Data Recovery Advisor fue introducido en Oracle 11g, una característica que ofrece recomendaciones respecto a fallas de bases de datos y también las repara si es posible. El DRA depende del Health Monitor para diagnósticos y puede ser usado por medio de RMAN o Enterprise Manager. Se ve bien pero ya que no tengo muchas bases de datos con fallas no tengo experiencia con él; sin embargo, tengo que estudiarlo para obtener la certificación de actualización de OCP 11g. A primera vista se ve como una buena característica para administradores con prisa o sin mucha experiencia, aunque personalmente prefiero hacer las cosas a mano y por mí mismo.

De cualquier forma, si quieres revisar las capacidades de DRA y tienes una base de datos para practicar podría valer el tiempo invertido en probar. El siguiente es un ejercicio para hacer eso, primero que nada, respalda tu base de datos ya que los respaldos son una parte importante de la recuperación usando DRA. Después, da de baja tu base de datos y renombra (o borra si tienes suficiente fé) un datafile, e intenta levantar tu base de datos:

oracle@olimpo:~$ sqlplus '/ as sysdba'

SQL*Plus: Release 11.2.0.1.0 Production on Wed Mar 6 13:35:56 2013

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

Connected to an idle instance.

SQL> startup
ORACLE instance started.

Total System Global Area  263639040 bytes
Fixed Size      1335892 bytes
Variable Size    213913004 bytes
Database Buffers    41943040 bytes
Redo Buffers      6447104 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 5 - see DBWR trace file
ORA-01110: data file 5: '/opt/oracle/oradata/orcl11g/example01.dbf'

La base de datos no se abrió como era de esperarse, por lo que el siguiente paso es ejecutar RMAN para usar el DRA. Como quizás sepas, es necesario tener al menos montada la base de datos para poder usar RMAN:

oracle@olimpo:~$ rman target /

Recovery Manager: Release 11.2.0.1.0 - Production on Wed Mar 6 13:36:56 2013

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

connected to target database: ORCL11G (DBID=915822427, not open)

El siguiente paso es listar las fallas actuales conocidas:

RMAN> list failure;

using target database control file instead of recovery catalog
List of Database Failures
=========================

Failure ID Priority Status    Time Detected Summary
---------- -------- --------- ------------- -------
42         HIGH     OPEN      06-MAR-13     One or more non-system datafiles are missing

Si quieres saber más detalles acerca de cierta falla también puedes hacerlo:

RMAN> list failure 42 detail;

List of Database Failures
=========================

Failure ID Priority Status    Time Detected Summary
---------- -------- --------- ------------- -------
42         HIGH     OPEN      06-MAR-13     One or more non-system datafiles are missing
  Impact: See impact for individual child failures
  List of child failures for parent failure ID 42
  Failure ID Priority Status    Time Detected Summary
  ---------- -------- --------- ------------- -------
  145        HIGH     OPEN      06-MAR-13     Datafile 5: '/opt/oracle/oradata/orcl11g/example01.dbf' is missing
    Impact: Some objects in tablespace EXAMPLE might be unavailable

El Health Monitor corre diagnósticos automáticamente cuando una falla elevada o crítica aparece, pero si por alguna razón no hay primero un diagnóstico hecho entonces no puedes obtener consejo respecto a esa falla. El siguiente paso es obtener consejo acerca de las fallas abiertas:

RMAN> advise failure;

List of Database Failures
=========================

Failure ID Priority Status    Time Detected Summary
---------- -------- --------- ------------- -------
42         HIGH     OPEN      06-MAR-13     One or more non-system datafiles are missing
  Impact: See impact for individual child failures
  List of child failures for parent failure ID 42
  Failure ID Priority Status    Time Detected Summary
  ---------- -------- --------- ------------- -------
  145        HIGH     OPEN      06-MAR-13     Datafile 5: '/opt/oracle/oradata/orcl11g/example01.dbf' is missing
    Impact: Some objects in tablespace EXAMPLE might be unavailable

analyzing automatic repair options; this may take some time
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=133 device type=DISK
analyzing automatic repair options complete

Mandatory Manual Actions
========================
no manual actions available

Optional Manual Actions
=======================
1. If file /opt/oracle/oradata/orcl11g/example01.dbf was unintentionally renamed or moved, restore it

Automated Repair Options
========================
Option Repair Description
------ ------------------
1      NOARCHIVELOG mode restore datafile 5  
  Strategy: The repair includes complete media recovery with no data loss
  Repair script: /opt/oracle/diag/rdbms/orcl11g/orcl11g/hm/reco_1400180561.hm

Como podrás imaginar, el DRA primero verifica prerequisitos relevantes e indispensables antes de dar cualquier opción de reparación automática, como respaldos de bases de datos. Las acciones manuales opcionales son recomendaciones sobre cómo resolver las fallas a mano, en lugar de dejar que el ADR las arregle automáticamente. Agunas veces tienes que llevar a cabo acciones manuales obligatorias antes de poder hacer cualquier reparación manual o automática, y en este caso no hay acciones manuales obligatorias a realizar.

Además, hay dos tipos de opciones de reparación: sin pérdida de datos y con pérdida de datos, asegúrate de revisar la estrategia para saber si la opción de reparación seleccionada no implica pérdida de datos, o por lo menos entender qué vas a perder si seleccionas esa opción en caso de que no haya mejor opción.

Adicionalmente, si quieres puedes revisar y modificar el script de reparación listado antes de hacer cualquier reparación, o puedes probar el procedimiento de reparación sin llevar a cabo ninguna reparación de esta forma:

RMAN> repair failure preview;

Strategy: The repair includes complete media recovery with no data loss
Repair script: /opt/oracle/diag/rdbms/orcl11g/orcl11g/hm/reco_1400180561.hm

contents of repair script:
   # NOARCHIVELOG mode restore datafile
   restore datafile 5;
   recover datafile 5;

Si estás contento con las opciones de reparación automáticas entonces puedes reparar las fallas abiertas de la base de datos de esta manera:

RMAN> repair failure;

Strategy: The repair includes complete media recovery with no data loss
Repair script: /opt/oracle/diag/rdbms/orcl11g/orcl11g/hm/reco_1400180561.hm

contents of repair script:
   # NOARCHIVELOG mode restore datafile
   restore datafile 5;
   recover datafile 5;

Do you really want to execute the above repair (enter YES or NO)? YES
executing repair script

Starting restore at 06-MAR-13
using channel ORA_DISK_1

channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00005 to /opt/oracle/oradata/orcl11g/example01.dbf
channel ORA_DISK_1: reading from backup piece /opt/oracle/flash_recovery_area/ORCL11G/backupset/2013_03_05/o1_mf_nnndf_TAG20130305T165413_8mdxwq5t_.bkp
channel ORA_DISK_1: piece handle=/opt/oracle/flash_recovery_area/ORCL11G/backupset/2013_03_05/o1_mf_nnndf_TAG20130305T165413_8mdxwq5t_.bkp tag=TAG20130305T165413
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:00:07
Finished restore at 06-MAR-13

Starting recover at 06-MAR-13
using channel ORA_DISK_1

starting media recovery
media recovery complete, elapsed time: 00:00:01

Finished recover at 06-MAR-13
repair failure complete

Do you want to open the database (enter YES or NO)? YES
database opened

RMAN> exit


Recovery Manager complete.

Tienes que confirmar que realmente quieres ejecutar las reparaciones, y como paso final podrías querer abrir la base de datos antes de salir de RMAN. Y eso es todo! En este caso todo salió bien y la base de datos fue reparada sin pérdida de datos:

oracle@olimpo:~$ sqlplus '/ as sysdba'

SQL*Plus: Release 11.2.0.1.0 Production on Wed Mar 6 13:43:10 2013

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


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> column INSTANCE_NAME format a20
SQL> column STATUS format a20
SQL> column DATABASE_STATUS format a20
SQL> select INSTANCE_NAME, STATUS, DATABASE_STATUS from v$instance;

INSTANCE_NAME      STATUS    DATABASE_STATUS
-------------------- -------------------- --------------------
orcl11g       OPEN    ACTIVE

Más información:

Diagnosing and Repairing Failures with Data Recovery Advisor

miércoles, 6 de marzo de 2013

Curso rápido de RMAN

Ha pasado mucho tiempo desde que publiqué mensajes aquí! En mi anterior trabajo (esta es mi segunda semana en el nuevo) no tuve muchas oportunidades de seguir publicando porque mi puesto no estaba relacionado ni con administración de servidores UNIX ni con administración de bases de datos, pero espero que este nuevo trabajo me dé mucho material para escribir mensajes interesantes.

Empecemos con algo simple, respaldar una base de datos Oracle con RMAN. Digamos que estás aprendiendo administración de bases de datos o tienes una base de datos pequeña y que no sea crítica que quieres respaldar, y no tienes inconveniente en usar la Flash Recovery Area; el directorio usado como FRA está definido por el parámetro db_recovery_file_dest en la base de datos. Primero que nada, tienes que configurar las variables de ambiente de Oracle necesarias para conectarte a la base de datos seleccionada:

oracle@olimpo:~/rman$ set|grep ORACLE
ORACLE_BASE=/opt/oracle
ORACLE_HOME=/opt/oracle/product/10.2.0/server
ORACLE_SID=orcl11g

Entonces puedes correr RMAN para conectarte a la base de datos actual (orcl11g):

oracle@olimpo:~/rman$ rman target /

Recovery Manager: Release 11.2.0.1.0 - Production on Tue Mar 5 16:53:00 2013

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

connected to target database: ORCL11G (DBID=915822427, not open)

Quizás notaste que mi base de datos no está abierta, eso es porque no tiene archive logs por lo que para hacer un respaldo consistente la puse en estado de montado. Si esta es la primera vez que ejecutas RMAN entonces sería bueno revisar sus parámetros:

RMAN> show all;
using target database control file instead of recovery catalog
RMAN configuration parameters for database with db_unique_name ORCL11G are:
CONFIGURE RETENTION POLICY TO REDUNDANCY 1; # default
CONFIGURE BACKUP OPTIMIZATION OFF; # default
CONFIGURE DEFAULT DEVICE TYPE TO DISK; # default
CONFIGURE CONTROLFILE AUTOBACKUP OFF; # default
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F'; # default
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 BACKUP TYPE TO BACKUPSET; # default
CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE MAXSETSIZE TO UNLIMITED; # default
CONFIGURE ENCRYPTION FOR DATABASE OFF; # default
CONFIGURE ENCRYPTION ALGORITHM 'AES128'; # default
CONFIGURE COMPRESSION ALGORITHM 'BASIC' AS OF RELEASE 'DEFAULT' OPTIMIZE FOR LOAD TRUE ; # default
CONFIGURE ARCHIVELOG DELETION POLICY TO NONE; # default
CONFIGURE SNAPSHOT CONTROLFILE NAME TO '/opt/oracle/product/10.2.0/server/dbs/snapcf_orcl11g.f'; # default

Por ejemplo, podrías querer revisar el algoritmo de compresión y la política de retención (cuántos respaldos quieres conservar al mismo tiempo); si quieres cambiar algo solo tienes que introducir el comando de la misma manera que se muestra:

RMAN> CONFIGURE RETENTION POLICY TO REDUNDANCY 2;
new RMAN configuration parameters:
CONFIGURE RETENTION POLICY TO REDUNDANCY 2;
new RMAN configuration parameters are successfully stored

RMAN> show all;
RMAN configuration parameters for database with db_unique_name ORCL11G are:
CONFIGURE RETENTION POLICY TO REDUNDANCY 2;
CONFIGURE BACKUP OPTIMIZATION OFF; # default
CONFIGURE DEFAULT DEVICE TYPE TO DISK; # default
CONFIGURE CONTROLFILE AUTOBACKUP OFF; # default
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '%F'; # default
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 BACKUP TYPE TO BACKUPSET; # default
CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1; # default
CONFIGURE MAXSETSIZE TO UNLIMITED; # default
CONFIGURE ENCRYPTION FOR DATABASE OFF; # default
CONFIGURE ENCRYPTION ALGORITHM 'AES128'; # default
CONFIGURE COMPRESSION ALGORITHM 'BASIC' AS OF RELEASE 'DEFAULT' OPTIMIZE FOR LOAD TRUE ; # default
CONFIGURE ARCHIVELOG DELETION POLICY TO NONE; # default
CONFIGURE SNAPSHOT CONTROLFILE NAME TO '/opt/oracle/product/10.2.0/server/dbs/snapcf_orcl11g.f'; # default

Entonces si estás listo para respaldar tu base de datos introduce este simple comando de respaldo:

RMAN> backup check logical database;

Starting backup at 05-MAR-13
using channel ORA_DISK_1
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00001 name=/opt/oracle/oradata/orcl11g/system01.dbf
input datafile file number=00002 name=/opt/oracle/oradata/orcl11g/sysaux01.dbf
input datafile file number=00005 name=/opt/oracle/oradata/orcl11g/example01.dbf
input datafile file number=00003 name=/opt/oracle/oradata/orcl11g/undotbs01.dbf
input datafile file number=00004 name=/opt/oracle/oradata/orcl11g/users01.dbf
channel ORA_DISK_1: starting piece 1 at 05-MAR-13
channel ORA_DISK_1: finished piece 1 at 05-MAR-13
piece handle=/opt/oracle/flash_recovery_area/ORCL11G/backupset/2013_03_05/o1_mf_nnndf_TAG20130305T165413_8mdxwq5t_.bkp tag=TAG20130305T165413 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:01:16
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
including current control file in backup set
including current SPFILE in backup set
channel ORA_DISK_1: starting piece 1 at 05-MAR-13
channel ORA_DISK_1: finished piece 1 at 05-MAR-13
piece handle=/opt/oracle/flash_recovery_area/ORCL11G/backupset/2013_03_05/o1_mf_ncsnf_TAG20130305T165413_8mdxz43d_.bkp tag=TAG20130305T165413 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:01
Finished backup at 05-MAR-13

De esta forma puedes respaldar una base de datos sin archive logs activados; si tienes una base de datos con archive logs activados entonces agrega la subcláusula plus archivelog al final del comando de respaldo. Además, la subcláusula check logical es para revisar errores lógicos en la base de datos mientras se hace el respaldo, el comando para respaldar una base de datos puede ser tan simple como backup database.

Ahora, si quieres revisar que tu respaldo está realmente ahí puedes hacerlo de esta forma:

RMAN> list backup summary;

List of Backups
===============
Key     TY LV S Device Type Completion Time #Pieces #Copies Compressed Tag
------- -- -- - ----------- --------------- ------- ------- ---------- ---
1       B  F  A DISK        05-MAR-13       1       1       NO         TAG20130305T165413
2       B  F  A DISK        05-MAR-13       1       1       NO         TAG20130305T165413

Pero espera, por qué hay dos respaldos en lugar de uno? Quizás una lista detallada podría mostrarnos por qué:

RMAN> list backup;

List of Backup Sets
===================


BS Key  Type LV Size       Device Type Elapsed Time Completion Time
------- ---- -- ---------- ----------- ------------ ---------------
1       Full    1.00G      DISK        00:01:15     05-MAR-13      
        BP Key: 1   Status: AVAILABLE  Compressed: NO  Tag: TAG20130305T165413
        Piece Name: /opt/oracle/flash_recovery_area/ORCL11G/backupset/2013_03_05/o1_mf_nnndf_TAG20130305T165413_8mdxwq5t_.bkp
  List of Datafiles in backup set 1
  File LV Type Ckp SCN    Ckp Time  Name
  ---- -- ---- ---------- --------- ----
  1       Full 854520     05-MAR-13 /opt/oracle/oradata/orcl11g/system01.dbf
  2       Full 854520     05-MAR-13 /opt/oracle/oradata/orcl11g/sysaux01.dbf
  3       Full 854520     05-MAR-13 /opt/oracle/oradata/orcl11g/undotbs01.dbf
  4       Full 854520     05-MAR-13 /opt/oracle/oradata/orcl11g/users01.dbf
  5       Full 854520     05-MAR-13 /opt/oracle/oradata/orcl11g/example01.dbf

BS Key  Type LV Size       Device Type Elapsed Time Completion Time
------- ---- -- ---------- ----------- ------------ ---------------
2       Full    9.36M      DISK        00:00:02     05-MAR-13      
        BP Key: 2   Status: AVAILABLE  Compressed: NO  Tag: TAG20130305T165413
        Piece Name: /opt/oracle/flash_recovery_area/ORCL11G/backupset/2013_03_05/o1_mf_ncsnf_TAG20130305T165413_8mdxz43d_.bkp
  SPFILE Included: Modification time: 05-MAR-13
  SPFILE db_unique_name: ORCL11G
  Control File Included: Ckp SCN: 854520       Ckp time: 05-MAR-13

El primer juego de respaldo es el respaldo completo de la base de datos, y el segundo es el respaldo del SPFILE de la base de datos, hecho por defecto. Y antes de salir de RMAN y para no llenar la FRA (su tamaño definido en el parámetro db_recovery_file_dest_size), borremos los respaldos obsoletos, o sea, los respaldos que ya no se necesitan de acuerdo a la política de retención:

RMAN> delete noprompt obsolete;
RMAN retention policy will be applied to the command
RMAN retention policy is set to redundancy 2
using channel ORA_DISK_1
no obsolete backups found

RMAN> quit

Recovery Manager complete.

Más información:

Getting Started with RMAN
Oracle Database Backup and Recovery Reference (Backup)

miércoles, 11 de abril de 2012

Error ORA-09817 y sistemas de archivos llenos

Digamos que estás intentando ingresar a tu base de datos y de pronto obtienes este mensaje de error:
oracle@mydb$ sqlplus '/ as sysdba'

SQL*Plus: Release 11.1.0.7.0 - Production on Mon Feb 13 15:47:27 2012

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

ERROR:
ORA-09817: Write to audit file failed.
SVR4 Error: 28: No space left on device
ORA-01075: you are currently logged on


Enter user-name: 

oracle@mydb$ 

Este es un problema fácil de adivinar y la clave está en el mensaje No space left on device. La instancia no puede escribir archivos de auditoría porque el sistema de archivos está lleno, por lo que tienes que averiguar por qué ese sistema de archivos está lleno:
oracle@mydb$ set | grep ORA
ORACLE_BASE=/oracle
ORACLE_HOME=/oracle/orahome
ORACLE_SID=mydb

oracle@mydb$ strings $ORACLE_HOME/dbs/*mydb.ora | grep audit_file_dest
*.audit_file_dest='/oracle/admin/mydb/adump'

oracle@mydb$ df -k | egrep '(Filesystem)|(/oracle)'
Filesystem                 kbytes    used   avail capacity  Mounted on
/dev/vx/dsk/orafs/oracle 16327680 16327680       0   100%    /oracle

En este caso el destino de los archivos de auditoría esta en el sistema de archivos base de Oracle, por lo tanto el problema podría estar en otro directorio:
oracle@mydb$ du -k /oracle | sort -nr | head 
16035094        /oracle
8412062 /oracle/diag
8297523 /oracle/diag/rdbms/mydb/mydb
8297523 /oracle/diag/rdbms/mydb
8297523 /oracle/diag/rdbms
8250027 /oracle/diag/rdbms/mydb/mydb/trace
6926099 /oracle/orahome
1631834 /oracle/orahome/mydirectory
938085  /oracle/orahome/mydirectory/somefiles
727017  /oracle/orahome/bin

oracle@mydb$ du -ka /oracle/diag/rdbms/mydb/mydb/trace | sort -nr | head
8250027 /oracle/diag/rdbms/mydb/mydb/trace
5737533 /oracle/diag/rdbms/mydb/mydb/trace/mydb_ora_5198.trc
2506955 /oracle/diag/rdbms/mydb/mydb/trace/mydb_ora_18305.trc
1946    /oracle/diag/rdbms/mydb/mydb/trace/mydb_ora_5198.trm
969     /oracle/diag/rdbms/mydb/mydb/trace/mydb_ora_18305.trm
457     /oracle/diag/rdbms/mydb/mydb/trace/mydb_ora_3695.trc
380     /oracle/diag/rdbms/mydb/mydb/trace/alert_mydb.log
314     /oracle/diag/rdbms/mydb/mydb/trace/mydb_j002_8800.trc
314     /oracle/diag/rdbms/mydb/mydb/trace/mydb_j002_13295.trc
314     /oracle/diag/rdbms/mydb/mydb/trace/mydb_j000_23311.trc

Aquí está el problema: hay dos archivos muy grandes de trazado que ocupan 8 gigabytes, la mitad del tamaño del sistema de archivos. Cuando averiguas por qué tu sistema de archivos está lleno tienes que decidir qué hacer, ya sea borrar, mover o comprimir archivos, sólo asegúrate de no desechar archivos que podrías necesitar.

lunes, 9 de abril de 2012

Creando tablas particionadas y error ORA-00922

Hay muchas versiones diferentes del software de Oracle Database y aún si la lógica y operaciones de la base de datos es más o menos la misma entre versiones, también es más o menos diferente entre versiones; por ejemplo, no hay sentencia drop database en Oracle 9i.

Entonces tu trabajas usualmente con bases de datos 11g y te encantan las tablas particionadas por intervalos, y creas una:
oracle@my11gdb~$ sqlplus '/ as sysdba'

SQL*Plus: Release 11.2.0.3.0 Production on Wed Feb 8 12:43:42 2012

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


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> CREATE TABLE MY_TABLE
(   
SOMETEXT     VARCHAR2(4000),
MOREINFO     VARCHAR2(256),
ADATE        DATE
) PARTITION BY RANGE (ADATE)
INTERVAL (NUMTODSINTERVAL(1,'day'))
(partition p0 values less than (to_date('01-jan-2000','dd-mon-yyyy'))
);

Table created.

E intentas crear esa misma tabla en una base de datos 10g sólo para encontrar que no puedes:
oracle@my10gdb~$ sqlplus '/ as sysdba'

SQL*Plus: Release 10.2.0.4.0 - Production on Wed Feb 8 12:46:15 2012

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options

SQL> CREATE TABLE MY_TABLE
(   
SOMETEXT     VARCHAR2(4000),
MOREINFO     VARCHAR2(256),
ADATE        DATE
) PARTITION BY RANGE (ADATE)
INTERVAL (NUMTODSINTERVAL(1,'day'))
(partition p0 values less than (to_date('01-jan-2000','dd-mon-yyyy'))
);
INTERVAL (NUMTODSINTERVAL(1,'day'))
*
ERROR at line 7:
ORA-00922: missing or invalid option

No busques más: el error ORA-00922 en una base de datos 10g significa que estás intentando usar una funcionalidad que no existe; en una base de datos 11g podría significar falta de paréntesis o errores de sintaxis.
oracle@my11gdb~$ sqlplus '/ as sysdba'

SQL*Plus: Release 11.2.0.3.0 Production on Wed Feb 8 12:50:54 2012

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


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> CREATE TABLE MY_TABLE
(   
SOMETEXT     VARCHAR2(4000),
MOREINFO     VARCHAR2(256),
ADATE        DATE
) PARTITION BY RANGE (ADATE)
INTERVAL (NUMTODSINTERVAL(1,'day'))
partition p0 values less than (to_date('01-jan-2000','dd-mon-yyyy'));
partition p0 values less than (to_date('01-jan-2000','dd-mon-yyyy'))
*
ERROR at line 8:
ORA-00922: missing or invalid option

Más información:

CREATE TABLE (10g Release 2)
CREATE TABLE (11g Release 1)
Partition Administration

sábado, 7 de abril de 2012

Bloqueando estadísticas de tablas

Tener estadísticas exactas de objetos de bases de datos es obligatorio para obtener la mejor trayectoria de ejecución, y usualmente puedes recabar estadísticas usando el paquete DBMS_STATS sin problemas. Pero algunas veces tienes tablas especiales que necesitan tratamiento especial, como tablas "temporales" (tablas normales que son llenadas y sus datos modificados muy rápido) que pueden cambiar mucho el plan de ejecución de una sentencia SQL y volverte loco tratando de averiguar la causa raíz de esos cambios del plan de ejecución.

Como demostración de este comportamiento crearemos dos tablas, una que cambiará mucho (test1) y otra que es más o menos estática (test2):
SQL> create table test1 (id number primary key, id_char varchar2(15));

Table created.

SQL> declare
mynum number := 1;
begin
while mynum < 10 loop
  insert into test1 values(mynum,to_char(mynum));
  mynum := mynum + 1;
  end loop;
end;
/

PL/SQL procedure successfully completed.

SQL> commit;

Commit complete.

SQL> create table test2 (id number primary key, id_char varchar2(15));

Table created.

SQL> declare
mynum number := 1;
begin
while mynum < 100000 loop
  insert into test2 values(mynum,to_char(mynum));
  mynum := mynum + 1;
  end loop;
end;
/

PL/SQL procedure successfully completed.

SQL> commit;

Commit complete.

Al principio la tabla test1 tiene 9 registros, y queremos unir las tablas test1 y test2 para obtener algunos registros, pero primero recopilaremos estadísticas de test1:
SQL> BEGIN DBMS_STATS.GATHER_TABLE_STATS( OWNNAME => 'MYUSER', TABNAME => 'TEST1'); END;
  2  /

PL/SQL procedure successfully completed.

SQL> select a.ID, b.ID_CHAR from test1 a join test2 b on (a.ID=b.ID) where a.ID between 4 and 7;

 ID         ID_CHAR
---------- ---------------
 4          4
 5          5
 6          6
 7          7

A continuación obtendremos el plan de ejecución actual para esta pequeña sentencia:
SQL> EXPLAIN PLAN FOR
select a.ID, b.ID_CHAR from test1 a join test2 b on (a.ID=b.ID) where a.ID between 4 and 7;

Explained.

SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3677731951

--------------------------------------------------------------------------------------------
| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |             |  4    | 56    |  4   (0)   | 00:00:01 |
|   1 |  NESTED LOOPS                |             |  4    | 56    |  4   (0)   | 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| TEST2       |  5    | 55    |  4   (0)   | 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | SYS_C004858 |  5    |       |  3   (0)   | 00:00:01 |
|*  4 |   INDEX UNIQUE SCAN          | SYS_C004857 |  1    |  3    |  0   (0)   | 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("B"."ID">=4 AND "B"."ID"<=7)
   4 - access("A"."ID"="B"."ID")
       filter("A"."ID">=4 AND "A"."ID"<=7)

18 rows selected.

Este plan de ejecución se ve bien y realmente no importa mucho ya que obtuvimos sólo unos cuantos registros, pero espera! Nueve registros no es el tamaño típico de la tabla test1; ahora crearemos más registros:
SQL> delete from test1;

9 rows deleted.

SQL> declare
mynum number := 1;
begin
while mynum < 10000 loop
  insert into test1 values(mynum,to_char(mynum));
  mynum := mynum + 1;
  end loop;
end;
/

PL/SQL procedure successfully completed.

SQL> commit;

Commit complete.

Podrías pensar que no hay mucha diferencia teniendo diez o diez mil registros en test1, pero el optimizador de Oracle no piensa lo mismo y esta vez el plan de ejecución es diferente:
SQL> EXPLAIN PLAN FOR
  2  select a.ID, b.ID_CHAR from test1 a join test2 b on (a.ID=b.ID) where a.ID between 4000 and 7000;

Explained.

SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2418654178

--------------------------------------------------------------------------------------------
| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |             |  1    | 14    |  3   (0)   | 00:00:01 |
|   1 |  NESTED LOOPS                |             |       |       |            |          |
|   2 |   NESTED LOOPS               |             |  1    | 14    |  3   (0)   | 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | SYS_C004857 |  1    |  3    |  1   (0)   | 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN         | SYS_C004858 |  1    |       |  1   (0)   | 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| TEST2       |  1    | 11    |  2   (0)   | 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("A"."ID">=4000 AND "A"."ID"<=7000)
   4 - access("A"."ID"="B"."ID")
       filter("B"."ID"<=7000 AND "B"."ID">=4000)

19 rows selected.

Podrías pensar que recuperar cuatro registros es diferente de recuperar cuatro mil y es correcto, pero el optimizador escogió el plan de ejecución basado en datos incorrectos; ve la cantidad de registros con los que Oracle piensa que va a trabajar.

Lo verás claramente actualizando las estadísticas de la tabla test1 y obteniendo la nueva trayectoria de ejecución:
SQL> BEGIN DBMS_STATS.GATHER_TABLE_STATS( OWNNAME => 'SYS', TABNAME => 'TEST1'); END;
  2  /

PL/SQL procedure successfully completed.

SQL> EXPLAIN PLAN FOR
select a.ID, b.ID_CHAR from test1 a join test2 b on (a.ID=b.ID) where a.ID between 4000 and 7000;

Explained.

SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3677731951

--------------------------------------------------------------------------------------------
| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |             |  3001 | 45015 | 17  (12)   | 00:00:01 |
|   1 |  NESTED LOOPS                |             |  3001 | 45015 | 17  (12)   | 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| TEST2       |  3002 | 33022 | 15   (0)   | 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | SYS_C004858 |  3002 |       |  8   (0)   | 00:00:01 |
|*  4 |   INDEX UNIQUE SCAN          | SYS_C004857 |  1    |  4    |  0   (0)   | 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("B"."ID">=4000 AND "B"."ID"<=7000)
   4 - access("A"."ID"="B"."ID")
       filter("A"."ID">=4000 AND "A"."ID"<=7000)

18 rows selected.

Puedes ver el problema? Teniendo que tratar con este tipo de tablas puedes: usar hints para forzar la ejecución óptima de la sentencia SQL, refrescar estadísticas cada vez que cambies una tabla como esta, o bloquear las estadísticas cuando tengas un tamaño típico de tabla o un plan de ejecución óptimo.

Consideraremos que en este punto la tabla test1 tiene un tamaño típico y sus estadísticas ayudan al optimizador a escoger un plan de ejecución óptimo, por lo tanto bloquearemos las estadísticas de esta forma:
SQL> exec DBMS_STATS.LOCK_TABLE_STATS ('MYUSER', 'TEST1');

PL/SQL procedure successfully completed.

Ahora volveremos a poner información en la tabla test1 con 9 registros:
SQL> delete from TEST1;

9999 rows deleted.

SQL> declare
mynum number := 1;
begin
while mynum < 10 loop
  insert into test1 values(mynum,to_char(mynum));
  mynum := mynum + 1;
  end loop;
end;
/

PL/SQL procedure successfully completed.

SQL> commit;

Commit complete.

SQL> BEGIN DBMS_STATS.GATHER_TABLE_STATS( OWNNAME => 'MYUSER', TABNAME => 'TEST1'); END;
  2  /
BEGIN DBMS_STATS.GATHER_TABLE_STATS( OWNNAME => 'MYUSER', TABNAME => 'TEST1'); END;
*
ERROR at line 1:
ORA-20005: object statistics are locked (stattype = ALL)
ORA-06512: at "SYS.DBMS_STATS", line 23829
ORA-06512: at "SYS.DBMS_STATS", line 23880
ORA-06512: at line 1

Ya que las estadísticas de la tabla test1 fueron bloqueadas no puedes recopilar nuevas estadísticas a menos que desbloquees las estadísticas de la tabla. De cualquier forma, el punto de hacer esto es ayudar al optimizador a escoger un buen plan de ejecución:
SQL> EXPLAIN PLAN FOR
select a.ID, b.ID_CHAR from test1 a join test2 b on (a.ID=b.ID) where a.ID between 4 and 7;

Explained.

SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3677731951

--------------------------------------------------------------------------------------------
| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |             |  4    | 60    |  4   (0)   | 00:00:01 |
|   1 |  NESTED LOOPS                |             |  4    | 60    |  4   (0)   | 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| TEST2       |  5    | 55    |  4   (0)   | 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | SYS_C004858 |  5    |       |  3   (0)   | 00:00:01 |
|*  4 |   INDEX UNIQUE SCAN          | SYS_C004857 |  1    |  4    |  0   (0)   | 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("B"."ID">=4 AND "B"."ID"<=7)
   4 - access("A"."ID"="B"."ID")
       filter("A"."ID"<=7 AND "A"."ID">=4)

18 rows selected.

SQL> delete from TEST1;

9 rows deleted.

SQL> declare
mynum number := 1;
begin
while mynum < 10000 loop
  insert into test1 values(mynum,to_char(mynum));
  mynum := mynum + 1;
  end loop;
end;
/

PL/SQL procedure successfully completed.

SQL> commit;

Commit complete.

SQL> EXPLAIN PLAN FOR
select a.ID, b.ID_CHAR from test1 a join test2 b on (a.ID=b.ID) where a.ID between 4000 and 7000;

Explained.

SQL> @$ORACLE_HOME/rdbms/admin/utlxpls.sql

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3677731951

--------------------------------------------------------------------------------------------
| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |             |  3001 | 45015 | 17  (12)   | 00:00:01 |
|   1 |  NESTED LOOPS                |             |  3001 | 45015 | 17  (12)   | 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| TEST2       |  3002 | 33022 | 15   (0)   | 00:00:01 |
|*  3 |    INDEX RANGE SCAN          | SYS_C004858 |  3002 |       |  8   (0)   | 00:00:01 |
|*  4 |   INDEX UNIQUE SCAN          | SYS_C004857 |  1    |  4    |  0   (0)   | 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("B"."ID">=4000 AND "B"."ID"<=7000)
   4 - access("A"."ID"="B"."ID")
       filter("A"."ID">=4000 AND "A"."ID"<=7000)

18 rows selected.

Como puedes ver, esta vez el plan de ejecución fue el mismo para diez o diez mil registros en la tabla test1 y el numero de registros manejados en los planes de ejecución fue más o menos preciso.

Por cierto, si quieres desbloquear las estadísticas de una tabla puedes hacerlo de esta forma:
SQL> exec DBMS_STATS.UNLOCK_TABLE_STATS ('MYUSER', 'TEST1');

PL/SQL procedure successfully completed.

SQL> BEGIN DBMS_STATS.GATHER_TABLE_STATS( OWNNAME => 'MYUSER', TABNAME => 'TEST1'); END;
  2  /

PL/SQL procedure successfully completed.


Más información:

Locking or Unlocking Statistics
Preserving Statistics using DBMS_STATS.LOCK_TABLE_STATS

jueves, 5 de abril de 2012

Oracle y OCFS2 sin liberar espacio usado

Algunas veces tienes que eliminar un tablespace para recuperar espacio de almacenamiento y usarlo para crear otro tablespace, como cuando tienes que redimensionar un tablespace de undo. Y usualmente no es gran problema a menos que tengas sistemas de archivos OCFS2:
oracle@myserver$ df -m|egrep '(Filesystem)|(/mydb/undo)'
Filesystem           1M-blocks      Used Available Use% Mounted on
                         24576     24572         4 100% /mydb/undo

oracle@myserver$ sqlplus '/ as sysdba'

SQL*Plus: Release 10.2.0.4.0 - Production on Thu Jan 26 22:57:35 2012

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options

SQL> drop tablespace myundo including contents and datafiles;

Tablespace dropped.

SQL> create undo tablespace mynewundo datafile '/mydb/undo/undo.dbf' size 10g;
create undo tablespace mynewundo datafile '/mydb/undo/undo.dbf' size 10g
*
ERROR at line 1:
ORA-01119: error in creating database file '/mydb/undo/undo.dbf'
ORA-27044: unable to write the header block of file
Linux-ia64 Error: 28: No space left on device
Additional information: 4

SQL> quit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options

oracle@myserver$ df -m|egrep '(Filesystem)|(/mydb/undo)'
Filesystem           1M-blocks      Used Available Use% Mounted on
                         24576     24572         4 100% /mydb/undo

oracle@myserver$ ls -la /mydb/undo
total 16
drwxr-xr-x  4 root   root 4096 Jan 20  2010 .
drwxr-xr-x  4 root   root 4096 Dec 17  2009 ..
drwxr-xr-x  2 root   root 4096 Dec 17  2009 lost+found

Como podrás haberte dado cuenta no hay espacio recuperado por eliminar ese tablespace de undo, y ya que necesitamos crear un nuevo tablespace de undo en el mismo sistema de archivos tenemos que hacer algo.

Yo no tengo muchas bases de datos ubicadas en sistemas de archivos OCFS2 por lo que no me preocupé por encontrar la causa raíz de este problema, y ya que tenía esta base de datos sin usuarios conectados sólo creé un pequeño tablespace de undo en otro lugar, di de baja la instancia, y después de hacerlo recuperé el espacio:
oracle@myserver$ df -m|egrep '(Filesystem)|(/mydb/undo)'
Filesystem           1M-blocks      Used Available Use% Mounted on
                         24576       359     24217   2% /mydb/undo

oracle@myserver$ ls -la /mydb/undo
total 16
drwxr-xr-x  4 root   root 4096 Jan 20  2010 .
drwxr-xr-x  4 root   root 4096 Dec 17  2009 ..
drwxr-xr-x  2 root   root 4096 Dec 17  2009 lost+found

oracle@myserver$ mount|grep /mydb/undo
/dev/mapper/myvg-undo on /mydb/undo type ocfs2 (rw,_netdev,datavolume,nointr,heartbeat=local)

oracle@myserver$ uname -a
Linux myserver.localdomain 2.6.9-67.EL #1 SMP Wed Nov 7 13:43:35 EST 2007 ia64 ia64 ia64 GNU/Linux

oracle@myserver$ /sbin/lsmod|grep ocf
ocfs2                 744096  26 
debugfs                27340  2 ocfs2
ocfs2_dlmfs            53416  1 
ocfs2_dlm             424192  2 ocfs2,ocfs2_dlmfs
ocfs2_nodemanager     316791  32 ocfs2,ocfs2_dlmfs,ocfs2_dlm
configfs               65468  2 ocfs2_nodemanager
jbd                   149272  2 ocfs2,ext3

oracle@myserver$ /sbin/modinfo ocfs2
filename:       /lib/modules/2.6.9-67.EL/kernel/fs/ocfs2/ocfs2.ko
license:        GPL
author:         Oracle
version:        1.2.9 1B43458FD47258934A48F1C
description:    OCFS2 1.2.9 Mon May 19 14:04:34 PDT 2008 (build a693806cb619dd7f225004092b675ede)
depends:        ocfs2_nodemanager,ocfs2_dlm,jbd,debugfs
vermagic:       2.6.9-67.EL SMP ia64gcc-3.4

Sé que este es sólo un arreglo temporal y no uno bueno, pero funciona bien y puedes continuar con lo que sigue.

miércoles, 28 de marzo de 2012

Datafiles de Oracle y archivos Quick I/O de Veritas

Si quieres tener máximo rendimiento en acceso a los datafiles debes usar dispositivos crudos para los datafiles, pero muchos sistemas operativos modernos manejan el acceso a archivos bastante bien, puedes usar ASM para la administración de almacenamiento de bases de datos Oracle, y administrar dispositivos crudos requiere un administrador de sistemas experimentado y es tardado, por lo que casi siempre la velocidad extra ganada con dispositivos crudos no vale la pena para la habilidad y esfuerzo extra requeridos para mantener dispositivos crudos.

Pero si tienes una base de datos Oracle en un servidor Solaris con sistema de archivos Veritas VxFS con Quick I/O incluido (esto es, con licencia), entonces puedes usar acceso Quick I/O con archivos regulares; de esta manera puedes tener y administrar archivos regulares pero al mismo tiempo puedes accesarlos como dispositivos crudos. Un usuario no privilegiado puede crear ligas Quick I/O y es muy fácil hacerlo; primero tienes que crear tu datafile a nivel de sistema operativo con qiomkfile:

oracle@myserver$ qiomkfile -h 32k -s 16000M /myfs/mydatabase/mydatafile.dbf

oracle@myserver$ ls -la /myfs/mydatabase
total 32768066
drwxr-xr-x 3 oracle dba 96 Sep 24 11:32 .
drwxr-xr-x 61 oracle dba 1024 Sep 23 16:57 ..
-rw-r--r-- 1 oracle dba 16777248768 Sep 24 11:32 .mydatafile.dbf
lrwxrwxrwx 1 oracle dba 26 Sep 24 11:32 mydatafile.dbf -> .mydatafile.dbf::cdev:vxfs:
drwxr-xr-x 2 oracle dba 96 Sep 23 16:50 lost+found

El secreto es que .mydatafile.dbf es un archivo regular (pero contínuo en toda su extensión), y mydatafile.dbf es una liga a .mydatafile.dbf::cdev:vxfs: pero el sistema operativo reconoce el sufijo ::cdev:vxfs: como Quick I/O y accesa .mydatafile.dbf como un dispositivo crudo; esta es la razón por la que el archivo .mydatafile.dbf::cdev:vxfs: no debe existir. Los parámetros de qiomkfile son simples; -h es el espacio extra agregado al archivo para usarlo como datafile de Oracle (en este caso 16,000 megabytes mas 32 kilobytes) ya que Oracle agrega un bloque de base de datos (parámetro DB_BLOCK_SIZE) para cada datafile creado, y -s es el tamaño requerido del datafile de Oracle que debe coincidir con la cláusula DATAFILE ... SIZE.

Esta fue la parte difícil; para crear datafiles que usen las características de Quick I/O tienes que usar la cláusula REUSE:

SQL> CREATE TABLESPACE MYTBL DATAFILE '/myfs/mydatabase/mydatafile.dbf' SIZE 16000M REUSE;

Tablespace created.

SQL> ALTER TABLESPACE MYTBL ADD DATAFILE '/myfs/mydatabase/mydatafile2.dbf' SIZE 16000M REUSE;

Tablespace altered.

Y hablando de eliminar tablespaces con datafiles con Quick I/O, no uses la cláusula INCLUDING CONTENTS AND DATAFILES u obtendrás un error, sólo elimina el tablespace y borra los archivos con rm a nivel de sistema operativo.

Más información:

Veritas Storage Foundation for Oracle Administrator’s Guide (chapter 4)
Veritas Storage Foundation 5.0 Software

martes, 27 de marzo de 2012

Acerca de las certificaciones Oracle OCA y OCP

Hace algún tiempo primero obtuve la certificación Oracle Certified Associate y después la certificación Oracle Certified Professional, ambas en Oracle Database 10g. Desde entonces ha habido personas que me preguntan sobre el procedimiento que seguí y también sobre el material de estudio que usé para prepararme para estos exámenes, y es hasta ahora que decidí escribir acerca de eso.

Antes que nada, los exámenes son de selección múltiple suficientemente difíciles para no permitirle pasar a cualquiera que pueda pagar el costo del examen (que por cierto considero bajo), y no ser un angloparlante nativo le agrega mucho más complejidad a los exámenes. Si tienes experiencia administrando bases de datos Oracle Y tienes un buen y fresco conocimiento de conceptos de bases de datos Oracle tendrás una buena oportunidad de pasar el examen; en este tipo de pruebas es muy importante tener conocimientos sólidos de conceptos ya que todas las respuestas se ven igual y las pequeñas diferencias son la clave para escoger la respuesta correcta, sin mencionar el tiempo limitado para responder el examen completo. Por cierto, recalqué el tener buenos conocimientos de inglés?

Por otro lado, si tienes un presupuesto bajo encontrarás que un estudio a fondo de la documentación oficial (y gratuita) de Oracle podría ser suficiente para pasar estos exámenes, e incluso la Express Edition (gratuita) es suficiente para practicar en tu propia computadora. Pero si dispones de un poco de dinero, recomiendo ampliamente comprar los exámenes de práctica de SelfTest Oracle Database 11g: SQL Fundamentals I, Oracle Database 10g: Administration I y Oracle Database 10g: Administration II; el precio de este software es cercano al precio de cada examen de certificación pero podría ahorrarte frustración y tiempo, sin mencionar dinero, por lo tanto tu decides prepararte para estos exámenes sólo con documentación gratuita (o cursos caros) o pagar el dinero extra para practicar las pruebas con este software. Si compras este software asegúrate de obtener al menos 90% de calificación algunas veces y tendrás una buena oportunidad de pasar las pruebas reales.

Pero si eres tacaño como yo podrías preferir estudiar la documentación oficial de Oracle. Para ser honestos, a estas alturas no recuerdo exactamente qué tuve que estudiar para cada examen de certificación, pero si estás dispuesto a obtener la certificación OCP simplemente estudia todas las guías siguientes y estarás bien.

Para la prueba de SQL (Oracle Database 11g: SQL Fundamentals I, 1Z0-051):

Oracle Database 2 Day DBA
Oracle Database Express Edition 2 Day Developer Guide

Para la certificación OCA (Oracle Database 10g: Administration I, 1Z0-042):

Oracle Database Administrator's Guide (capítulos 1 al 20)
Oracle Database Backup and Recovery Basics

Para la certificación OCP (Oracle Database 10g: Administration II, 1Z0-043):

Oracle Database Administrator's Guide (capítulos 21 al 28)
Oracle Database Backup and Recovery Advanced User's Guide

El problema de estudiar la documentación de Oracle es que no está pensada para ser una guía de autoaprendizaje, por lo tanto tienes que pensar ejercicios para practicar lo que lees; sólo leyendo esta documentación sin practicar ni tener experiencia no será suficiente para aprobar los exámenes. Pero en mi experiencia personal creo que estas guías están tan bien escritas que si puedes aprenderlas no tendrás ninguna necesidad de comprar (o leer) otros libros; de hecho no puedo recomendar libros porque yo no leí nada excepto las guías de Oracle para prepararme para los exámenes de certificación.

Otro problema es que estas guías son buenas para prepararse para los exámenes de OCA y OCP, pero para el examen de SQL Fundamentals no pude encontrar una guía de Oracle que cubriera todo; de hecho estuve muy cerca de reprobar ese examen pero el software de SelfTest me salvó. Por otro lado, el examen de OCA se me hizo difícil pero fue mucho menos difícil que el examen de SQL, y el examen de OCP fue el más sencillo de todos para mi. Por lo tanto, si tu eres un administrador de bases de datos más que un desarrollador será mejor estudiar a conciencia sentencias SQL y funciones.

Ahora hablemos sobre el camino de certificación y los prerequisitos. Si tu objetivo son las certificaciones OCP u OCA primero tienes que pasar uno de los exámenes de SQL, más probablemente el de Oracle Database 11g: SQL Fundamentals I. Puedes hacer los exámenes OCA u OCP primero pero no obtendrás ninguna certificación a menos que completes todos los prerequisitos de la certificación, por lo tanto primero intenta pasar el examen de SQL.

Si pasas el examen de SQL podrás presentar el examen Oracle Database 10g: Administration I, y si lo apruebas tendrás la certificación OCA. Fácil, verdad?

Pero esto es sólo el comienzo, la meta debe ser la certificación OCP pero hay dos prerequisitos no tan fáciles de cubrir: tomar un curso aprobado y llenar el formato de envío de curso. La parte difícil de tomar un curso aprobado es sólo pagar por él, y si tu diploma del curso tienen un numero de serie del curso y tomaste ese curso recientemente no tendrás problemas llenando el formato de envío de curso.

Al momento de escribir esto, el envío del formato y la programación de los exámenes debe ser hecha en el sitio de Pearson Vue, y desafortunadamente no puedo recordar qué hice exactamente pero podrías obtener ayuda al momento de contactar un centro de evaluación.

Finalmente, si cumpliste con todos los prerequisitos y lograste pasar el examen Oracle Database 10g: Administration II, te convertirás en un Oracle Certified Professional y obtendrás una bonita tarjeta de plástico sólo en caso de que quieras presumir acerca de ello.

Hay gente que cuestiona el valor de este tipo de certificaciones, pero la verdad es que yo aprendí mucho estudiando para los exámenes de certificación, y debido a que esas certificaciones son válidas en todo el mundo son un buen punto de referencia para reclutadores en busca de talento. Por lo tanto, si ya tomaste un curso aprobado por Oracle pon un poco de esfuerzo y dinero y ve por las certificaciones OCA y OCP, pienso que tienen buen valor por lo que cuestan.

lunes, 26 de marzo de 2012

Parchando una base de datos Oracle RAC

Parchar una base de datos Oracle RAC es un poco diferente de parchar una base de datos de una sola instancia debido a que tienes que parchar al menos dos instalaciones (CRS, base de datos y ASM si existe), parcharlas en cierto orden, y dar de baja y levantar servicios de CRS inexistentes en instalaciones de una sola instancia; puedes incluso aplicar parches con o sin dar de baja la base de datos RAC completa, y aplicarlos en cada nodo o propagar los parches a todos los nodos ejecutando el parchado en un solo nodo.

En este ejemplo parcharemos una base de datos Oracle 10g RAC de dos nodos (10.2.0.1) con ASM, compartiendo la base de datos y ASM la misma instalación, primero actualizándola al parche 10.2.0.5.0 y finalmente al PSU 10.2.0.5.4, dando de baja completamente la base de datos RAC y aplicando los parches en ambos nodos desde uno de ellos. Las recomendaciones usuales aplican: leer la documentación del parche y respaldar tu base de datos y la instalación Oracle antes de parchar.

Primero descargaremos los parches 8202632 (parche 10.2.0.5.0), 12419392 (PSU 10.2.0.5.4), y 6880880 (Opatch 10.2.0.5.1), y los descomprimiremos en un nodo al menos:

oracle@myracn1$ ls -la
total 2659400
drwxr-xr-x 4 oracle dba 512 Nov 17 18:20 .
drwxr-xr-x 23 oracle dba 1024 Nov 17 13:03 ..
drwxr-xr-x 5 oracle dba 512 Jun 16 00:42 12419392
drwxr-xr-x 6 oracle dba 512 Nov 17 15:16 Disk1
-rw-r--r-- 1 oracle dba 11319286 Nov 15 21:33 p12419392_10205_SOLARIS64.zip
-rw-r--r-- 1 oracle dba 28674793 Nov 17 18:17 p6880880_102000_SOLARIS64.zip
-rw-r--r-- 1 oracle dba 1320728471 Nov 15 21:36 p8202632_10205_SOLARIS64.zip
-rwxr-xr-x 1 oracle dba 175026 May 19 2010 README.html

A continuación, daremos de baja todas las instancias de RAC y servicios:

oracle@myracn1$ srvctl stop database -d myrcdb
oracle@myracn1$ srvctl stop asm -n myracn1
oracle@myracn1$ srvctl stop asm -n myracn2
oracle@myracn1$ srvctl stop listener -n myracn1
oracle@myracn1$ srvctl stop listener -n myracn2
oracle@myracn1$ srvctl stop nodeapps -n myracn1
oracle@myracn1$ srvctl stop nodeapps -n myracn2

oracle@myracn1$ cd /opt/oracle/crs/bin

oracle@myracn1$ ./crs_stat -t
Name Type Target State Host
------------------------------------------------------------
ora....SM1.asm application ONLINE OFFLINE
ora....T2.lsnr application OFFLINE OFFLINE
ora.myracn1.gsd application OFFLINE OFFLINE
ora.myracn1.ons application OFFLINE OFFLINE
ora.myracn1.vip application OFFLINE OFFLINE
ora....SM2.asm application ONLINE OFFLINE
ora....T4.lsnr application OFFLINE OFFLINE
ora.myracn2.gsd application OFFLINE OFFLINE
ora.myracn2.ons application OFFLINE OFFLINE
ora.myracn2.vip application OFFLINE OFFLINE
ora.myrcdb.db application ONLINE OFFLINE
ora....l1.inst application ONLINE OFFLINE
ora....l2.inst application ONLINE OFFLINE

Después ejecutaremos OUI para parchar primero el software CRS. Es muy sencillo seguir las instrucciones del Oracle Universal Installer, solo tienes que seleccionar la instalación de CRS cuando aplique y estar seguro de seleccionar todos los nodos de RAC para instalar este parche; todo lo demás es muy sencillo.

oracle@myracn1$ cd /opt/oracle/parches/Disk1

oracle@myracn1$ ./runInstaller
Starting Oracle Universal Installer...

Checking installer requirements...

Checking operating system version: must be 5.8, 5.9 or 5.10. Actual 5.10
Passed

Checking Temp space: must be greater than 250 MB. Actual 13017 MB Passed
Checking swap space: must be greater than 500 MB. Actual 15218 MB Passed
Checking monitor: must be configured to display at least 256 colors. Actual 16777216 Passed

All installer requirements met.

Preparing to launch Oracle Universal Installer from /tmp/OraInstall2011-11-17_01-45-53PM. Please wait ...
oracle@myracn1$ Oracle Universal Installer, Version 10.2.0.5.0 Production
Copyright (C) 1999, 2010, Oracle. All rights reserved.

Warning: Cannot convert string "-monotype-arial-regular-r-normal--*-140-*-*-p-*-iso8859-1" to type FontStruct

Como paso final de esta aplicación de parche y antes de salir de OUI, tenemos que correr el script root102.sh como root después de detener los servicios CRS, en todos los nodos de RAC:

oracle@myracn1$ su -
Password:

root@myracn1# /opt/oracle/crs/bin/crsctl stop crs
Stopping resources.
Successfully stopped CRS resources
Stopping CSSD.
Shutting down CSS daemon.
Shutdown request successfully issued.

root@myracn1# /opt/oracle/crs/install/root102.sh
Creating pre-patch directory for saving pre-patch clusterware files
Completed patching clusterware files to /opt/oracle/crs
Relinking some shared libraries.
ar: writing /opt/oracle/crs/lib/libn10.a
ar: writing /opt/oracle/crs/lib32/libn10.a
ar: writing /opt/oracle/crs/lib/libn10.a
Relinking of patched files is complete.
WARNING: directory '/opt/oracle' is not owned by root
Preparing to recopy patched init and RC scripts.
Recopying init and RC scripts.
Startup will be queued to init within 30 seconds.
Starting up the CRS daemons.
Waiting for the patched CRS daemons to start.
This may take a while on some systems.
.
10205 patch successfully applied.
clscfg: EXISTING configuration version 3 detected.
clscfg: version 3 is 10G Release 2.
Successfully deleted 1 values from OCR.
Successfully deleted 1 keys from OCR.
Successfully accumulated necessary OCR keys.
Using ports: CSS=49895 CRS=49896 EVMC=49898 and EVMR=49897.
node :
node 1: myracn1 myracn1-priv myracn1
Creating OCR keys for user 'root', privgrp 'root'..
Operation successful.
clscfg -upgrade completed successfully
Creating '/opt/oracle/crs/install/paramfile.crs' with data used for CRS configuration
Setting CRS configuration values in /opt/oracle/crs/install/paramfile.crs

root@myracn1# exit

En este punto tenemos el software CRS parchado en todos los nodos, por lo tanto parcharemos el ASM y la base de datos a continuación. En este ejemplo ASM y la base de datos comparten la misma instalación, pero de otra forma tienes que parchar primero la instalación ASM y después la instalación de la base de datos.

Sólo en caso de que aún no lo hayas notado, el parche 10.2.0.5 es el mismo parche para CRS, ASM y base de datos, por lo tanto aplicaremos el mismo parche casi de la misma manera que antes pero esta vez seleccionaremos la instalación de ASM y base de datos, por supuesto después de dar de baja todas las instancias de la base de datos RAC y los servicios:

oracle@myracn1$ srvctl stop database -d myrcdb
oracle@myracn1$ srvctl stop asm -n myracn1
oracle@myracn1$ srvctl stop asm -n myracn2
oracle@myracn1$ srvctl stop listener -n myracn1
oracle@myracn1$ srvctl stop listener -n myracn2
oracle@myracn1$ srvctl stop nodeapps -n myracn1
oracle@myracn1$ srvctl stop nodeapps -n myracn2

oracle@myracn1$ cd -
/opt/oracle/crs/bin

oracle@myracn1$ ./crs_stat -t
Name Type Target State Host
------------------------------------------------------------
ora....SM1.asm application ONLINE OFFLINE
ora....T2.lsnr application OFFLINE OFFLINE
ora.myracn1.gsd application OFFLINE OFFLINE
ora.myracn1.ons application OFFLINE OFFLINE
ora.myracn1.vip application OFFLINE OFFLINE
ora....SM2.asm application ONLINE OFFLINE
ora....T4.lsnr application OFFLINE OFFLINE
ora.myracn2.gsd application OFFLINE OFFLINE
ora.myracn2.ons application OFFLINE OFFLINE
ora.myracn2.vip application OFFLINE OFFLINE
ora.myrcdb.db application ONLINE OFFLINE
ora....l1.inst application ONLINE OFFLINE
ora....l2.inst application ONLINE OFFLINE

oracle@myracn1$ cd -
/opt/oracle/parches/Disk1

oracle@myracn1$ ./runInstaller
Starting Oracle Universal Installer...

Checking installer requirements...

Checking operating system version: must be 5.8, 5.9 or 5.10. Actual 5.10
Passed

Checking Temp space: must be greater than 250 MB. Actual 12967 MB Passed
Checking swap space: must be greater than 500 MB. Actual 15169 MB Passed
Checking monitor: must be configured to display at least 256 colors. Actual 16777216 Passed

All installer requirements met.

Preparing to launch Oracle Universal Installer from /tmp/OraInstall2011-11-17_02-23-05PM. Please wait ...
oracle@myracn1$ Oracle Universal Installer, Version 10.2.0.5.0 Production
Copyright (C) 1999, 2010, Oracle. All rights reserved.

Warning: Cannot convert string "-monotype-arial-regular-r-normal--*-140-*-*-p-*-iso8859-1" to type FontStruct

Como antes, tenemos que correr como root el script root.sh antes de salir del Oracle Universal Installer, en todos los nodos de RAC:

oracle@myracn1$ su -
Password:
root@myracn1# /opt/oracle/db/root.sh
Running Oracle 10g root.sh script...

The following environment variables are set as:
ORACLE_OWNER= oracle
ORACLE_HOME= /opt/oracle/db

Enter the full pathname of the local bin directory: [/usr/local/bin]:
The file "dbhome" already exists in /usr/local/bin. Overwrite it? (y/n) [n]: y
Copying dbhome to /usr/local/bin ...
The file "oraenv" already exists in /usr/local/bin. Overwrite it? (y/n) [n]: y
Copying oraenv to /usr/local/bin ...
The file "coraenv" already exists in /usr/local/bin. Overwrite it? (y/n) [n]: y
Copying coraenv to /usr/local/bin ...

Entries will be added to the /var/opt/opt/oracle/oratab file as needed by
Database Configuration Assistant when a database is created
Finished running generic part of root.sh script.
Now product-specific root actions will be performed.

root@myracn1# exit

En este punto tenemos el parche 10.2.0.5 aplicado a nivel de software, por lo que el siguiente paso es levantar los servicios de ASM y RAC sin las instancias de las bases de datos:

oracle@myracn1$ srvctl start listener -n myracn1
oracle@myracn1$ srvctl start listener -n myracn2
oracle@myracn1$ srvctl start nodeapps -n myracn1
oracle@myracn1$ srvctl start nodeapps -n myracn2

oracle@myracn1$ ./crs_stat -t
Name Type Target State Host
------------------------------------------------------------
ora....SM1.asm application ONLINE OFFLINE
ora....T2.lsnr application ONLINE ONLINE myracn1
ora.myracn1.gsd application ONLINE ONLINE myracn1
ora.myracn1.ons application ONLINE ONLINE myracn1
ora.myracn1.vip application ONLINE ONLINE myracn1
ora....SM2.asm application ONLINE OFFLINE
ora....T4.lsnr application ONLINE ONLINE myracn2
ora.myracn2.gsd application ONLINE ONLINE myracn2
ora.myracn2.ons application ONLINE ONLINE myracn2
ora.myracn2.vip application ONLINE ONLINE myracn2
ora.myrcdb.db application ONLINE OFFLINE
ora....l1.inst application ONLINE OFFLINE
ora....l2.inst application ONLINE OFFLINE

oracle@myracn1$ srvctl start asm -n myracn1
oracle@myracn1$ srvctl start asm -n myracn2

oracle@myracn1$ ps -fea|grep pmon
oracle 8812 6323 0 15:08:58 pts/1 0:00 grep pmon
oracle 5280 1 0 15:03:28 ? 0:01 asm_pmon_+ASM1

Para actualizar el catálogo de las bases de datos configuraremos el parámetro CLUSTER_DATABASE como falso para levantar sólo una instancia; tienes que hacer esto sólo en la instancia en la que vas a trabajar, pero el procedimiento completo de actualizar el catálogo se debe hacer en cada base de datos del RAC.

Sólo para ser claros, en este ejemplo estamos trabajando con un ASM y una base base de datos normal (myrcdb) en un cluster RAC con dos nodos; hay una instancia de ASM corriendo en cada nodo (dos instancias de ASM en total), y también una instancia de la base de datos myrcdb corriendo en cada nodo (dos instancias de base de datos en total).

Además, no tienes que ejecutar una actualización de catálogo en una instancia ASM, sólo en instancias de bases de datos.

oracle@myracn1$ sqlplus '/ as sysdba'

SQL*Plus: Release 10.2.0.5.0 - Production on Thu Nov 17 15:09:17 2011

Copyright (c) 1982, 2010, Oracle. All Rights Reserved.

Connected to an idle instance.

SQL> startup nomount
ORACLE instance started.

Total System Global Area 1610612736 bytes
Fixed Size 2052448 bytes
Variable Size 385879712 bytes
Database Buffers 1207959552 bytes
Redo Buffers 14721024 bytes
SQL> ALTER SYSTEM SET CLUSTER_DATABASE=FALSE SCOPE=spfile;

System altered.

SQL> shutdown
ORA-01507: database not mounted


ORACLE instance shut down.
SQL> exit

Antes de ejecutar el script de actualización del catálogo levantaremos la instancia en modo de actualización, y como buena práctica, ejecutaremos el script de información de actualización para verificar si todo está bien para actualizar el catálogo.

oracle@myracn1$ sqlplus '/ as sysdba'

SQL*Plus: Release 10.2.0.5.0 - Production on Thu Nov 17 15:11:33 2011

Copyright (c) 1982, 2010, Oracle. All Rights Reserved.

Connected to an idle instance.

SQL> startup upgrade;
ORACLE instance started.

Total System Global Area 1610612736 bytes
Fixed Size 2052448 bytes
Variable Size 385879712 bytes
Database Buffers 1207959552 bytes
Redo Buffers 14721024 bytes
Database mounted.
Database opened.
SQL> @?/rdbms/admin/utlu102i.sql
Oracle Database 10.2 Upgrade Information Utility 11-17-2011 15:13:03
.
**********************************************************************
Database:
**********************************************************************
--> name: myrcdb
--> version: 10.2.0.1.0
--> compatible: 10.2.0.1.0
--> blocksize: 8192
.
**********************************************************************
Tablespaces: [make adjustments in the current environment]
**********************************************************************
--> SYSTEM tablespace is adequate for the upgrade.
.... minimum required size: 420 MB
--> UNDOTBS1 tablespace is adequate for the upgrade.
.... minimum required size: 402 MB
.... AUTOEXTEND additional space required: 202 MB
--> SYSAUX tablespace is adequate for the upgrade.
.... minimum required size: 185 MB
.... AUTOEXTEND additional space required: 5 MB
--> TEMP tablespace is adequate for the upgrade.
.... minimum required size: 58 MB
.... AUTOEXTEND additional space required: 38 MB
.
**********************************************************************
Update Parameters: [Update Oracle Database 10.2 init.ora or spfile]
**********************************************************************
-- No update parameter changes are required.
.
**********************************************************************
Renamed Parameters: [Update Oracle Database 10.2 init.ora or spfile]
**********************************************************************
-- No renamed parameters found. No changes are required.
.
**********************************************************************
Obsolete/Deprecated Parameters: [Update Oracle Database 10.2 init.ora or spfile]
**********************************************************************
-- No obsolete parameters found. No changes are required
.
**********************************************************************
Components: [The following database components will be upgraded or installed]
**********************************************************************
--> Oracle Catalog Views [upgrade] VALID
--> Oracle Packages and Types [upgrade] VALID
--> JServer JAVA Virtual Machine [upgrade] VALID
--> Oracle XDK for Java [upgrade] VALID
--> Oracle Java Packages [upgrade] VALID
--> Oracle XML Database [upgrade] VALID
--> Real Application Clusters [upgrade] VALID
--> Oracle Workspace Manager [upgrade] VALID
--> Oracle interMedia [upgrade] VALID
--> Expression Filter [upgrade] VALID
--> Rule Manager [upgrade] VALID
.

PL/SQL procedure successfully completed.

Lee cuidadosamente el reporte del script de información de actualización y realiza cualquier cambio sugerido; puedes sólo ejecutar el script de actualización del catálogo pero si ignoras sugerencias de este reporte la actualización podría fallar, y no quieres terminar con un catálogo corrupto, créeme.

Después de esto ejecutaremos el script de actalización del catálogo; recuerda, tienes que ejecutar este script en cada base de datos que tengas en tu cluster RAC, pero sólo en una instancia por base de datos:

SQL> spool patch.log
SQL> @?/rdbms/admin/catupgrd.sql

...

PL/SQL procedure successfully completed.


PL/SQL procedure successfully completed.


TIMESTAMP
--------------------------------------------------------------------------------
COMP_TIMESTAMP UPGRD_END 2011-11-17 17:20:37

1 row selected.

.
Oracle Database 10.2 Upgrade Status Utility 11-17-2011 17:20:37
.
Component Status Version HH:MM:SS
Oracle Database Server VALID 10.2.0.5.0 00:54:11
JServer JAVA Virtual Machine VALID 10.2.0.5.0 00:15:23
Oracle XDK VALID 10.2.0.5.0 00:02:40
Oracle Database Java Packages VALID 10.2.0.5.0 00:01:21
Oracle XML Database VALID 10.2.0.5.0 00:12:22
Oracle Real Application Clusters VALID 10.2.0.5.0 00:00:06
Oracle Workspace Manager VALID 10.2.0.5.0 00:04:02
Oracle interMedia VALID 10.2.0.5.0 00:24:00
Oracle Expression Filter VALID 10.2.0.5.0 00:00:58
Oracle Rule Manager VALID 10.2.0.5.0 00:00:47
.
Total Upgrade Time: 02:04:12

PL/SQL procedure successfully completed.

DOC>#######################################################################
DOC>#######################################################################
DOC>
DOC> The above PL/SQL lists the SERVER components in the upgraded
DOC> database, along with their current version and status.
DOC>
DOC> Please review the status and version columns and look for
DOC> any errors in the spool log file. If there are errors in the spool
DOC> file, or any components are not VALID or not the current version,
DOC> consult the Oracle Database Upgrade Guide for troubleshooting
DOC> recommendations.
DOC>
DOC> Next shutdown immediate, restart for normal operation, and then
DOC> run utlrp.sql to recompile any invalid application objects.
DOC>
DOC>#######################################################################
DOC>#######################################################################
DOC>#
SQL> spool off

Como se menciona en el mensaje final del script catupgrd.sql revisa que todos los componentes estén presentes, tengan un estado válido y versión adecuada, y sólo para estar seguros revisa el archivo patch.log sobre mensajes de error ORA.

En este punto casi hemos terminado la aplicación del parche 10.2.0.5, y recompilaremos y buscaremos objetos inválidos:

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options

oracle@myracn1$ sqlplus '/ as sysdba'

SQL*Plus: Release 10.2.0.5.0 - Production on Thu Nov 17 17:23:06 2011

Copyright (c) 1982, 2010, Oracle. All Rights Reserved.

Connected to an idle instance.

SQL> startup
ORACLE instance started.

Total System Global Area 1610612736 bytes
Fixed Size 2052448 bytes
Variable Size 436211360 bytes
Database Buffers 1157627904 bytes
Redo Buffers 14721024 bytes
Database mounted.
Database opened.
SQL> @?/rdbms/admin/utlrp.sql

TIMESTAMP
--------------------------------------------------------------------------------
COMP_TIMESTAMP UTLRP_BGN 2011-11-17 17:24:02

DOC> The following PL/SQL block invokes UTL_RECOMP to recompile invalid
DOC> objects in the database. Recompilation time is proportional to the
DOC> number of invalid objects in the database, so this command may take
DOC> a long time to execute on a database with a large number of invalid
DOC> objects.


...


DOC> The following query reports the number of objects that have compiled
DOC> with errors (objects that compile with errors have status set to 3 in
DOC> obj$). If the number is higher than expected, please examine the error
DOC> messages reported with each object (using SHOW ERRORS) to see if they
DOC> point to system misconfiguration or resource constraints that must be
DOC> fixed before attempting to recompile these objects.
DOC>#

OBJECTS WITH ERRORS
-------------------
0

DOC> The following query reports the number of errors caught during
DOC> recompilation. If this number is non-zero, please query the error
DOC> messages in the table UTL_RECOMP_ERRORS to see if any of these errors
DOC> are due to misconfiguration or resource constraints that must be
DOC> fixed before objects can compile successfully.
DOC>#

ERRORS DURING RECOMPILATION
---------------------------
0


PL/SQL procedure successfully completed.

SQL> column COMP_NAME format a50
SQL> column VERSION format a15
SQL> SELECT COMP_NAME, VERSION, STATUS FROM SYS.DBA_REGISTRY;

COMP_NAME VERSION STATUS
-------------------------------------------------- --------------- -----------
Oracle interMedia 10.2.0.5.0 VALID
Oracle XML Database 10.2.0.5.0 VALID
Oracle Expression Filter 10.2.0.5.0 VALID
Oracle Rule Manager 10.2.0.5.0 VALID
Oracle Workspace Manager 10.2.0.5.0 VALID
Oracle Database Catalog Views 10.2.0.5.0 VALID
Oracle Database Packages and Types 10.2.0.5.0 VALID
JServer JAVA Virtual Machine 10.2.0.5.0 VALID
Oracle XDK 10.2.0.5.0 VALID
Oracle Database Java Packages 10.2.0.5.0 VALID
Oracle Real Application Clusters 10.2.0.5.0 VALID

11 rows selected.

Si todo se ve bien, sólo tenemos que restaurar el valor del parámetro CLUSTER_DATABASE a verdadero y levantar la base de datos RAC y los servicios:

SQL> ALTER SYSTEM SET CLUSTER_DATABASE=TRUE SCOPE=spfile;

System altered.

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options

oracle@myracn1$ srvctl start nodeapps -n myracn1
oracle@myracn1$ srvctl start nodeapps -n myracn2
oracle@myracn1$ srvctl start listener -n myracn1
oracle@myracn1$ srvctl start listener -n myracn2
oracle@myracn1$ srvctl start asm -n myracn1
oracle@myracn1$ srvctl start asm -n myracn2
oracle@myracn1$ srvctl start database -d myrcdb

oracle@myracn1$ cd -
/opt/oracle/crs/bin

oracle@myracn1$ ./crs_stat -t
Name Type Target State Host
------------------------------------------------------------
ora....SM1.asm application ONLINE ONLINE myracn1
ora....T2.lsnr application ONLINE ONLINE myracn1
ora.myracn1.gsd application ONLINE ONLINE myracn1
ora.myracn1.ons application ONLINE ONLINE myracn1
ora.myracn1.vip application ONLINE ONLINE myracn1
ora....SM2.asm application ONLINE ONLINE myracn2
ora....T4.lsnr application ONLINE ONLINE myracn2
ora.myracn2.gsd application ONLINE ONLINE myracn2
ora.myracn2.ons application ONLINE ONLINE myracn2
ora.myracn2.vip application ONLINE ONLINE myracn2
ora.myrcdb.db application ONLINE ONLINE myracn2
ora....l1.inst application ONLINE ONLINE myracn1
ora....l2.inst application ONLINE ONLINE myracn2

Terminamos la aplicación del parche 10.2.0.5 en nuestro Oracle RAC! Ahora aplicaremos el PSU 10.2.0.5.4 sólo para estar completamente actualizados, pero primero una rápida revisión del inventario:

oracle@myracn1$ export PATH=$PATH:$ORACLE_HOME/OPatch

oracle@myracn1$ opatch lsinventory
Invoking OPatch 10.2.0.4.9

Oracle Interim Patch Installer version 10.2.0.4.9
Copyright (c) 2009, Oracle Corporation. All rights reserved.


Oracle Home : /opt/oracle/db
Central Inventory : /opt/oracle/oraInventory
from : /var/opt/opt/oracle/oraInst.loc
OPatch version : 10.2.0.4.9
OUI version : 10.2.0.5.0
OUI location : /opt/oracle/db/oui
Log file location : /opt/oracle/db/cfgtoollogs/opatch/opatch2011-11-17_17-48-04PM.log

Patch history file: /opt/oracle/db/cfgtoollogs/opatch/opatch_history.txt

Lsinventory Output file location : /opt/oracle/db/cfgtoollogs/opatch/lsinv/lsinventory2011-11-17_17-48-04PM.txt

--------------------------------------------------------------------------------
Installed Top-level Products (2):

Oracle Database 10g 10.2.0.1.0
Oracle Database 10g Release 2 Patch Set 4 10.2.0.5.0
There are 2 products installed in this Oracle Home.


There are no Interim patches installed in this Oracle Home.


Rac system comprising of multiple nodes
Local node = myracn1
Remote node = myracn2

--------------------------------------------------------------------------------

OPatch succeeded.

A continuación, dar de baja todas las instancias RAC y los servicios:

oracle@myracn1$ srvctl stop database -d myrcdb
oracle@myracn1$ srvctl stop asm -n myracn1
oracle@myracn1$ srvctl stop asm -n myracn2
oracle@myracn1$ srvctl stop listener -n myracn1
oracle@myracn1$ srvctl stop listener -n myracn2
oracle@myracn1$ srvctl stop nodeapps -n myracn1
oracle@myracn1$ srvctl stop nodeapps -n myracn2

oracle@myracn1$ cd /opt/oracle/crs/bin

oracle@myracn1$ ./crs_stat -t
Name Type Target State Host
------------------------------------------------------------
ora....SM1.asm application ONLINE OFFLINE
ora....T2.lsnr application OFFLINE OFFLINE
ora.myracn1.gsd application OFFLINE OFFLINE
ora.myracn1.ons application OFFLINE OFFLINE
ora.myracn1.vip application OFFLINE OFFLINE
ora....SM2.asm application ONLINE OFFLINE
ora....T4.lsnr application OFFLINE OFFLINE
ora.myracn2.gsd application OFFLINE OFFLINE
ora.myracn2.ons application OFFLINE OFFLINE
ora.myracn2.vip application OFFLINE OFFLINE
ora.myrcdb.db application ONLINE OFFLINE
ora....l1.inst application ONLINE OFFLINE
ora....l2.inst application ONLINE OFFLINE

Después, intentamos aplicar el PSU pero ...

oracle@myracn1$ cd /opt/oracle/parches
oracle@myracn1$ opatch napply 12419392 -all_nodes
Invoking OPatch 10.2.0.4.9

Oracle Interim Patch Installer version 10.2.0.4.9
Copyright (c) 2009, Oracle Corporation. All rights reserved.

UTIL session

Oracle Home : /opt/oracle/db
Central Inventory : /opt/oracle/oraInventory
from : /var/opt/opt/oracle/oraInst.loc
OPatch version : 10.2.0.4.9
OUI version : 10.2.0.5.0
OUI location : /opt/oracle/db/oui
Log file location : /opt/oracle/db/cfgtoollogs/opatch/opatch2011-11-17_17-48-44PM.log

Patch history file: /opt/oracle/db/cfgtoollogs/opatch/opatch_history.txt

Invoking utility "napply"
UtilSession failed:

Patch 12419392 requires OPatch version 10.2.0.5.0.
The OPatch version being used (10.2.0.4.9) doesn't meet the minimum version required by the patch(es). Please download latest OPatch from My Oracle Support.


OPatch failed with error code 73

Esto es por qué descargamos el parche 6880880; para aplicar el PSU 10.2.0.5.4 necesitamos un OPatch versión 10.2.0.5.0 o superior.

Como sea, es muy sencillo actualizar OPatch, sólo tenemos que eliminar el directorio original de OPatch y descomprimir el nuevo en el Oracle Home:

oracle@myracn1$ cd $ORACLE_HOME
oracle@myracn1$ rm -r OPatch
oracle@myracn1$ unzip /opt/oracle/parches/p6880880_102000_SOLARIS64.zip
Archive: /opt/oracle/parches/p6880880_102000_SOLARIS64.zip
creating: OPatch/
creating: OPatch/ocm/
extracting: OPatch/ocm/ocm.zip
creating: OPatch/ocm/lib/
inflating: OPatch/ocm/lib/osdt_jce.jar

...


inflating: OPatch/docs/Prereq_Users_Guide.txt
inflating: OPatch/docs/FAQ
inflating: OPatch/docs/Users_Guide.txt
inflating: OPatch/README.txt

oracle@myracn1$ ls -la OPatch/
total 120
drwxr-xr-x 7 oracle dba 512 Nov 17 18:20 .
drwxr-x--- 62 oracle dba 1536 Nov 17 18:20 ..
drwxr-xr-x 3 oracle dba 512 Nov 3 2010 crs
drwxr-xr-x 2 oracle dba 512 Nov 3 2010 docs
-rw-r--r-- 1 oracle dba 23695 Nov 3 2010 emdpatch.pl
drwxr-xr-x 2 oracle dba 512 Nov 3 2010 jlib
drwxr-xr-x 4 oracle dba 512 Nov 3 2010 ocm
-r-x--x--- 1 oracle dba 13252 Nov 3 2010 opatch
-rwxr-xr-x 1 oracle dba 8085 Nov 3 2010 opatch.bat
-rw-r--r-- 1 oracle dba 49 Nov 3 2010 opatch.ini
-rw-r--r-- 1 oracle dba 2576 Nov 3 2010 opatch.pl
drwxr-xr-x 4 oracle dba 512 Nov 3 2010 opatchprereqs
-rw-r--r-- 1 oracle dba 2417 Nov 3 2010 README.txt

Con OPatch actualizado ahora sí estamos listos para aplicar el PSU a todos los nodos RAC al mismo tiempo, y afortunadamente en el caso de este parche sólo tenemos que responder algunas sencillas preguntas:

oracle@myracn1$ cd /opt/oracle/parches

oracle@myracn1$ opatch napply 12419392 -all_nodes
Invoking OPatch 10.2.0.5.1

Oracle Interim Patch Installer version 10.2.0.5.1
Copyright (c) 2010, Oracle Corporation. All rights reserved.

UTIL session

Oracle Home : /opt/oracle/db
Central Inventory : /opt/oracle/oraInventory
from : /var/opt/opt/oracle/oraInst.loc
OPatch version : 10.2.0.5.1
OUI version : 10.2.0.5.0
OUI location : /opt/oracle/db/oui
Log file location : /opt/oracle/db/cfgtoollogs/opatch/opatch2011-11-17_18-23-00PM.log

Patch history file: /opt/oracle/db/cfgtoollogs/opatch/opatch_history.txt

Invoking utility "napply"
Checking conflict among patches...
Checking if Oracle Home has components required by patches...
Checking conflicts against Oracle Home...
OPatch continues with these patches: 12419392

Do you want to proceed? [y|n]
y
User Responded with: Y

Running prerequisite checks...
Provide your email address to be informed of security issues, install and
initiate Oracle Configuration Manager. Easier for you if you use your My
Oracle Support Email address/User Name.
Visit http://www.oracle.com/support/policies.html for details.
Email address/User Name:

You have not provided an email address for notification of security issues.
Do you wish to remain uninformed of security issues ([Y]es, [N]o) [N]: Y

OPatch detected the node list and the local node from the inventory. OPatch will patch the local system then propagate the patch to the remote nodes.


This node is part of an Oracle Real Application Cluster.
Remote nodes: 'myracn2'
Local node: 'myracn1'
Please shut down Oracle instances running out of this ORACLE_HOME on all the nodes.
(Oracle Home = '/opt/oracle/db')


Are all the nodes ready for patching? [y|n]
y
User Responded with: Y
Backing up files affected by the patch 'NApply' for restore. This might take a while...
Execution of 'sh /opt/oracle/parches/12419392/custom/scripts/pre -apply 12419392 ':


Return Code = 0

Applying patch 12419392...

ApplySession applying interim patch '12419392' to OH '/opt/oracle/db'
ApplySession: Optional component(s) [ oracle.rdbms.dv, 10.2.0.5.0 ] , [ oracle.rdbms.dv.oc4j, 10.2.0.5.0 ] not present in the Oracle Home or a higher version is found.
Backing up files affected by the patch '12419392' for rollback. This might take a while...

Patching component oracle.rdbms, 10.2.0.5.0...
Updating archive file "/opt/oracle/db/lib/libserver10.a" with "lib/libserver10.a/kcbl.o"
Updating archive file "/opt/oracle/db/lib/libserver10.a" with "lib/libserver10.a/qecsel.o"


...


Updating jar file "/opt/oracle/db/sysman/jlib/emjsp.jar" with "/sysman/jlib/emjsp.jar/_database/_dbObjectsList.class"
Copying file to "/opt/oracle/db/oc4j/j2ee/oc4j_applications/applications/em/em/admin/rep/editUserSummary.uix"

Patching component oracle.xdk.rsf, 10.2.0.5.0...
Updating archive file "/opt/oracle/db/lib/libxml10.a" with "lib/libxml10.a/lpxpar.o"
Updating archive file "/opt/oracle/db/lib32/libxml10.a" with "lib32/libxml10.a/lpxpar.o"

Patching component oracle.precomp.common, 10.2.0.5.0...

Patching component oracle.rdbms.rman, 10.2.0.5.0...
ApplySession adding interim patch '12419392' to inventory

Verifying the update...
Inventory check OK: Patch ID 12419392 is registered in Oracle Home inventory with proper meta-data.
Files check OK: Files from Patch ID 12419392 are present in Oracle Home.
Running make for target client_sharedlib
Running make for target ioracle
Running make for target iwrap
Running make for target client_sharedlib
Running make for target proc
Running make for target irman

The local system has been patched and can be restarted.


Patching in all-node mode.

Updating nodes 'myracn2'
Apply-related files are:
FP = "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/copy_files.txt"
DP = "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/copy_dirs.txt"
MP = "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/make_cmds.txt"
RC = "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/remote_cmds.txt"

Instantiating the file "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/copy_files.txt.instantiated" by replacing $ORACLE_HOME in "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/copy_files.txt" with actual path.
Propagating files to remote nodes...
Instantiating the file "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/copy_dirs.txt.instantiated" by replacing $ORACLE_HOME in "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/copy_dirs.txt" with actual path.
Propagating directories to remote nodes...
Instantiating the file "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/make_cmds.txt.instantiated" by replacing $ORACLE_HOME in "/opt/oracle/db/.patch_storage/NApply/2011-11-17_18-23-00PM/rac/make_cmds.txt" with actual path.
Running command on remote node 'myracn2':
cd /opt/oracle/db/rdbms/lib; /usr/ccs/bin/make -f ins_rdbms.mk client_sharedlib ORACLE_HOME=/opt/oracle/db || echo REMOTE_MAKE_FAILED::>&2

Running command on remote node 'myracn2':
cd /opt/oracle/db/rdbms/lib; /usr/ccs/bin/make -f ins_rdbms.mk ioracle ORACLE_HOME=/opt/oracle/db || echo REMOTE_MAKE_FAILED::>&2

Running command on remote node 'myracn2':
cd /opt/oracle/db/plsql/lib; /usr/ccs/bin/make -f ins_plsql.mk iwrap ORACLE_HOME=/opt/oracle/db || echo REMOTE_MAKE_FAILED::>&2

Running command on remote node 'myracn2':
cd /opt/oracle/db/network/lib; /usr/ccs/bin/make -f ins_net_client.mk client_sharedlib ORACLE_HOME=/opt/oracle/db || echo REMOTE_MAKE_FAILED::>&2

Running command on remote node 'myracn2':
cd /opt/oracle/db/precomp/lib; /usr/ccs/bin/make -f ins_precomp.mk proc ORACLE_HOME=/opt/oracle/db || echo REMOTE_MAKE_FAILED::>&2

Running command on remote node 'myracn2':
cd /opt/oracle/db/rdbms/lib; /usr/ccs/bin/make -f ins_rdbms.mk irman ORACLE_HOME=/opt/oracle/db || echo REMOTE_MAKE_FAILED::>&2

RC file not exist. There are no commands to be run on the remote nodes.

All nodes have been patched. You may start Oracle instances on the local system and nodes 'myracn2'

UtilSession: N-Apply done.

OPatch succeeded.

Aplicar un PSU es más rápido que aplicar un parche que necesita OUI, pero para este PSU en particular también necesitamos actualizar el catálogo de la base de datos después de levantar la base de datos RAC y los servicios:

oracle@myracn1$ srvctl start nodeapps -n myracn1
oracle@myracn1$ srvctl start nodeapps -n myracn2
oracle@myracn1$ srvctl start listener -n myracn1
oracle@myracn1$ srvctl start listener -n myracn2
oracle@myracn1$ srvctl start asm -n myracn1
oracle@myracn1$ srvctl start asm -n myracn2
oracle@myracn1$ srvctl start database -d myrcdb

oracle@myracn1$ cd /opt/oracle/crs/bin

oracle@myracn1$ ./crs_stat -t
Name Type Target State Host
------------------------------------------------------------
ora....SM1.asm application ONLINE ONLINE myracn1
ora....T2.lsnr application ONLINE ONLINE myracn1
ora.myracn1.gsd application ONLINE ONLINE myracn1
ora.myracn1.ons application ONLINE ONLINE myracn1
ora.myracn1.vip application ONLINE ONLINE myracn1
ora....SM2.asm application ONLINE ONLINE myracn2
ora....T4.lsnr application ONLINE ONLINE myracn2
ora.myracn2.gsd application ONLINE ONLINE myracn2
ora.myracn2.ons application ONLINE ONLINE myracn2
ora.myracn2.vip application ONLINE ONLINE myracn2
ora.myrcdb.db application ONLINE ONLINE myracn1
ora....l1.inst application ONLINE ONLINE myracn1
ora....l2.inst application ONLINE ONLINE myracn2

Para actualizar el catálogo de la base de datos ejecutaremos el script catbundle.sql para cada base de datos en el RAC pero sólo una vez; para este ejemplo lo ejecutaremos para myrcdb sólo una vez:

oracle@myracn1$ sqlplus '/ as sysdba'

SQL*Plus: Release 10.2.0.5.0 - Production on Thu Nov 17 18:43:44 2011

Copyright (c) 1982, 2010, Oracle. All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options

SQL> @?/rdbms/admin/catbundle.sql psu apply

PL/SQL procedure successfully completed.


PL/SQL procedure successfully completed.


Generating apply and rollback scripts...


...


Updating registry...

1 row created.


Commit complete.

Check the following log file for errors:
/opt/oracle/db/cfgtoollogs/catbundle/catbundle_PSU_myrcdb_APPLY_2011Nov17_18_44_18.log

Como fue sugerido, sería buena idea revisar el archivo de log sobre errores ORA sólo para estar seguros. Y como último paso, recompilaremos y buscaremos objetos inválidos:

SQL> @?/rdbms/admin/utlrp.sql

TIMESTAMP
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COMP_TIMESTAMP UTLRP_BGN 2011-11-17 18:44:47

DOC> The following PL/SQL block invokes UTL_RECOMP to recompile invalid
DOC> objects in the database. Recompilation time is proportional to the
DOC> number of invalid objects in the database, so this command may take
DOC> a long time to execute on a database with a large number of invalid
DOC> objects.


...


DOC> The following query reports the number of objects that have compiled
DOC> with errors (objects that compile with errors have status set to 3 in
DOC> obj$). If the number is higher than expected, please examine the error
DOC> messages reported with each object (using SHOW ERRORS) to see if they
DOC> point to system misconfiguration or resource constraints that must be
DOC> fixed before attempting to recompile these objects.
DOC>#

OBJECTS WITH ERRORS
-------------------
0

DOC> The following query reports the number of errors caught during
DOC> recompilation. If this number is non-zero, please query the error
DOC> messages in the table UTL_RECOMP_ERRORS to see if any of these errors
DOC> are due to misconfiguration or resource constraints that must be
DOC> fixed before objects can compile successfully.
DOC>#

ERRORS DURING RECOMPILATION
---------------------------
0


PL/SQL procedure successfully completed.

SQL> exit

Eso es! En este punto tenemos un cluster RAC actualizado con Oracle 10.2.0.5.4; tuvimos que dar de baja el servicio de bases de datos para plicar este parche pero de esta manera es mas fácil y rápido que aplicar un parche con el método rolling upgrade. Hacer una actualización por etapas significa aplicar un parche sin tiempo abajo del servicio, pero el parche debe ser adecuado para este método y es más complejo y tardado que sólo dar de baja un RAC y aplicar un parche.

Listando el inventario puedes verificar que el parche 12419392 está registrado:

oracle@myracn1$ opatch lsinventory
Invoking OPatch 10.2.0.5.1

Oracle Interim Patch Installer version 10.2.0.5.1
Copyright (c) 2010, Oracle Corporation. All rights reserved.


Oracle Home : /opt/oracle/db
Central Inventory : /opt/oracle/oraInventory
from : /var/opt/opt/oracle/oraInst.loc
OPatch version : 10.2.0.5.1
OUI version : 10.2.0.5.0
OUI location : /opt/oracle/db/oui
Log file location : /opt/oracle/db/cfgtoollogs/opatch/opatch2011-11-17_18-46-17PM.log

Patch history file: /opt/oracle/db/cfgtoollogs/opatch/opatch_history.txt

Lsinventory Output file location : /opt/oracle/db/cfgtoollogs/opatch/lsinv/lsinventory2011-11-17_18-46-17PM.txt

--------------------------------------------------------------------------------
Installed Top-level Products (2):

Oracle Database 10g 10.2.0.1.0
Oracle Database 10g Release 2 Patch Set 4 10.2.0.5.0
There are 2 products installed in this Oracle Home.


Interim patches (1) :

Patch 12419392 : applied on Thu Nov 17 18:28:53 CST 2011
Unique Patch ID: 13856866
Created on 15 Jun 2011, 22:41:17 hrs PST8PDT
Bugs fixed:
6402302, 10269717, 10327190, 8865718, 10017048, 9024850, 8394351, 8546356
9360157, 9770451, 9020537, 9772888, 8664189, 10091698, 12551710, 7519406
10132870, 8771916, 9109487, 10173237, 10068982, 8350262, 11792865
11724962, 11725006, 9184754, 8544696, 9320130, 7026523, 8277300, 9726739
8412426, 12419392, 6651220, 9150282, 9659614, 9949948, 10327179, 8882576
7612454, 9711859, 9714832, 10248542, 9952230, 9469117, 9952270, 8660422
10324526, 12419258, 9713537, 10010310, 9390484, 9963497, 12551700
12551701, 10249537, 12551702, 12551703, 8211733, 12551704, 9548269
12551705, 12551706, 9337325, 12551707, 7602341, 12551708, 9308296
10157402, 11737047



Rac system comprising of multiple nodes
Local node = myracn1
Remote node = myracn2

--------------------------------------------------------------------------------

OPatch succeeded.

Por cierto, notaste que no hubo PSU para CRS? Usualmente hay el mismo parche y PSU para todos los componentes de Oracle Database (CRS, ASM, bases de datos), y también para todas las plataformas, pero en este caso en particular no hubo PSU 10.2.0.5.4 para CRS. Si lo hay, sería preferible (o incluso obligatorio) tiener el mismo parche y PSU en todos los componentes de Oracle Database, pero en esta ocasión está bien así.

Más información:

10.2.0.5 Current Recommended Patches