Escribir la salida de un sql en un fichero con UTL_FILE

Vamos con otra entrada básica para dummies.

Supongamos que queremos hacer implantar algún tipo de sonda que nos haga una pregunta a la base de datos y nos deje el resultado en un directorio.
Vamos a crear un pequeño procedimiento que, a modo de ejemplo nos saque algunos parámetros del v$session y nos lo deje en un directorio previamente definido llamado SONDA

CREATE OR REPLACE PROCEDURE proc_a_file AS
     fichero utl_file.file_type;
     nombre_fichero  VARCHAR2(255);
     linea_resul  VARCHAR2(255);
        BEGIN
  -- Definimos el nombre del log de salida
     select  'sonda_'||
              to_char(TO_CHAR(sysdate, 'YYYYMMDDHHmiss'))||
             '.log'
              into nombre_fichero  from dual  ;
  -- Abrimos fichero      
       fichero := utl_file.fopen('SONDA', nombre_fichero, 'A');
  -- Añadimos encabezado   
           UTL_FILE.PUT_LINE ( fichero ,'SID, SERIAL,TERMINAL,OSUSER');
  -- Lanzamos consulta        
                     FOR ciclo IN (
                         SELECT
                              select sid SID,
                              serial#  SERIAL,
                              terminal TEMINAL,
                              osuser  USER  
                         from v$session
                               )
                  LOOP  --Bucle de scritura de datos 
                 UTL_FILE.PUT_LINE ( fichero ,ciclo.SID||
                                              chr(44)|| 
                                             ciclo.SERIAL||
                                              chr(44)|| 
                                            ciclo.TERMINAL||
                                            chr(44)||
                                            ciclo.USER);
                 END LOOP;         
-- Limpiamos y cerramos
          utl_file.fflush(fichero);
        utl_file.fclose(fichero);
-- Excepciones de error en el alert.log
    EXCEPTION
    WHEN UTL_FILE.WRITE_ERROR THEN
    dbms_system.ksdwrt(2, 'ORA-XXXX  Error en procedure proc_a_file escrbiendo en fichero de log.');
    WHEN others THEN
       dbms_system.ksdwrt(2, 'ORA-XXXX  Error genérico en procedure   proc_a_file. '||SQLERRM);
      END proc_a_file; -- En del procedure

Ahora ya podemos lanzar nuestro procedimiento, bien desde el código de aplicación, cron, task manager, trigger o desde el lugar que deseemos

Instalando Oracle 12c en linux

A primeros de este mes Oracle anuncio el lanzamiento de la versión 12c de Oracle.En el post de hoy vamos a ver como se hace la instalación para Oracle Linux 6.4
La mayor ventaja de el uso de Oracle Linux va a ser que como veremos la instalación será practicamente limpia.

Los prerrequisitos van a ser los mismos que en versiones anteriores de Oracle, instalaremos un Oracle Linux, y crearemos un usuario oracle y un grupo oinstall

La primera imagen que vemos es una pantalla con los colores corporativos y un aspecto mas renovado.

1

Tras esta pantalla, nos viene la tipica imagen en la que nos solicita nuestro usuario de soporte. Nosotros le diremos que no queremos actualizaciones de Oracle.
2

También omitiremos la opcion de registrarla automáticamente con metalink.

3

Tras estas primeras pantallas, llegamos a la opción de crear base de datos, instalar o actualizar, nosotros vamos a probar la instalación en un servidor limpio.En otra entrada probaremos como funciona la actualización, aunque, siempre soy mas partidario de instalar en otro entorno y actualizar despues la base de datos

4

En la siguiente pantalla nos encontramos una opcion nueva y , para mi bastante sorprendente, «escritorio o servidor» .
Sinceramente no se que puede ser una «instalacion de escritorio» de oracle, con lo que, directamente iremos a servidor
5

La siguiente pantalla es bastante mas interesante, además de las opciones clásicas de base de datos «alone» o «Rac», nos aparece la nueva entrada de «Rac OneNode»
En esta entrada haremos una instalación «alone», dejando la de RAC ONE NODE para otra entrada.
Como aperitivo, os diré que el producto Rac One Node es la respuesta de Oracle a la necesidad de una alta disponibilidad «activo/pasivo».
6

Seleccionamos instalación avalada
7

En ingles
8

y Enterprise ( como decía mi abuela, «ande o no ande la burra grande»)
9

En la siguiente pantalla al fin empezamos a elegir opciones de la base de datos.
Al tratarse de una primera instalación de base de datos de pruebas en un entorno virtual vamos a ir a lo fácil y elegiremos una instalación en filesystem.

instalacion oracle 12c paso 9

Indicamos donde queremos el orainventory y el grupo de instalacion (oinstall)
instalacion oracle 12c paso  10
Y el tipo de base de datos (en nuestro caso es indiferente)
instalacion oracle 12c paso 11

En el paso 13 además del SID nos encontramos con una opción interesante, la creación de un contenedor de bases de datos, nosotros vamos a dejarlo como nos pide por defecto

instalacion oracle 12c paso 13
Asignamos la memoria y el juego de caracteres
instalacion oracle 12c paso 13

Y la ubicación de los datafiles (en nuestro caso lo haremos sencillo indicándole que queremos un directorio en el filesystem)
instalacion oracle 12c paso 14

Nosotros no vamos a registrarla en ningun cloud control, ni activaremos la FRA (lo haremos después )

instalacion oracle 12c paso 15
instalacion oracle 12c paso 16

La siguiente pantalla es la de las contraseñas, dado que es un entorno de pruebas, vamos ha hacer la poco recomendable opción de poner en todas la misma
instalacion oracle 12c paso 17 instalacion oracle 12c paso 17[/caption]instalacion oracle 12c paso 18

Al fin llegamos al punto 20, el punto de las comprobaciones, aquí veremos si tenemos todos los parámetros del kernel y paquetes.
instalacion oracle 12c paso 20

Tras esto llegamos a la ventana de resumen, esta version 12c tiene dos mejoras considerables

  • Opcion de editar directamente los puntos que te puedan parecer incorrectos
  • Opcion de generar un fichero de respuesta con las opciones que has creado de la base de datos

instalacion oracle 12c paso 20

Con toda esta información oracle se pondrá a instalar hasta la habitual pantalla en la que nos pide que ejecutemos como root 2 scripts en el filesystem
21

22

tras esto ya solamente queda que cree nuestra base de datos y ya tendremos nuestra version de Oracle 12c funcionando

Detectando bloques corruptos en Oracle

Hoy vamos a ver como detectar que se nos ha roto en casos de problemas de bloques corruptos de Oracle.

Lo primero que tenemos que tener en mente es tener la base de datos en modo archivelog y hacer copias periódicas con RMAN, pero , ¿que ocurre si no es así y tenemos una corrupción de datos?
Seguramente habremos perdido esos bloques. Pero, lo primero va a ser el saber que objetos lógicos tenemos corruptos .

Tenemos dos maneras de detectar la corrupción de datos

RMAN

Si tenemos la base de datos en modo archivelog ejecutaremos

 rman target / nocatalog
run {
allocate channel d1 type disk;
backup check logical validate database;
release channel d1;
}

El comando validate de RMAN hará un chequeo de los bloques inválidos y nos los dejará en la vista v$database_block_corruption;

DBVERIFY

Si no tenemos la base de datos en modo archivelog, no podemos usar RMAN (a no ser que esté en modo MOUNT), asi que,usaermos dbv.

Oracle provee en todas las plataformas el comando de sistema operativo DBVERIFY (dbv) que nos permite el llevar a cabo una comprobación de la integridad física de los ficheros de la base de datos.Su gran ventaja es que no necesita corte de servicio y podemos ejecutarlo tranquilamente mientras los usuarios trabajan en la base de datos.

La sintaxis la podemos ver en http://docs.oracle.com/cd/A97630_01/server.920/a96652/ch13.htm , y su principal inconveniente es que debe lanzarse para cada uno de los datafiles de la base de datos.

Una manera rápida de automatizar el comando para toda la base de datos es mediante el siguiente script ejecutado como sys o system

spool /tmp/datafiles_corruptos.sh
set linesize 200
set heading off
set pagesize 200
select 'dbv  file=' || name || ' blocksize=' || block_size || 
       ' feedback=' || round(blocks*.10,0)||
       '  logfile=' || file# || '.log'
          from v$datafile;

Este script nos dejara un fichero /tmp/datafiles_corruptos.sh con tantas líneas como datafiles tenga la base de datos de la forma

dbv  file=/opt/oracle/oradata/pruebas/tablespace_indices001.dbf blocksize=8192 feedback=3840  logfile=2

El comando dbv nos va a generar un fichero de log de nombre DATAFILE#.log, con lo que, mi consejo es crear un subdirectorio y lanzar el script /tmp/datafiles_corruptos.sh desde este subdirectorio, asi no llenaremos el path donde nos encontremos de ficheros de log.

EL detectar lo bloques inválidos es muy sencillo, solamente tenemos que ordenar por tamaño de fichero en el subdirectorio que tenemos los logs. Los ficheros que no tienen bloques corruptos tendrás un tamaño aproximado de 1 Km y su contenido será similar a :

DBVERIFY: Release 11.2.0.3.0 - Production on Jue Jun 6 13:14:28 2013
Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.
DBVERIFY - Iniciando verificación : FILE =/opt/oracle/oradata/pruebas/tablespace_indices018.dbf
DBVERIFY - Verificación terminada
Total de Páginas Examinadas     : 153600
Total de Páginas Procesadas (Datos): 91682
Total de Páginas con Fallos (Datos): 0
Total de Páginas Procesadas (Índice): 28488
Total de Páginas con Fallos (Índice): 0
Total de Páginas Procesadas (Otras): 17288
Total de Páginas Procesadas (Seg): 1
Total de Páginas con Fallos (Seg): 0
Total de Páginas Vacías         : 16142
Total de Páginas Marcadas como Corruptas: 0
Total de Páginas de Entrada     : 0
Total de Páginas Cifradas        : 0
SCN de Bloque Superior            : 1961026896 (9.1961026896)

Los datafiles con bloques corruptos tendrán un tamaño mayor, y su contenido será

DBVERIFY: Release 11.2.0.3.0 - Production on Jue Jun 6 13:16:14 2013
Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.
DBVERIFY - Iniciando verificación : FILE = /opt/oracle/oradata/pruebas/SYSAUX01.DBF
La página 45847 es de entrada - probablemente el medio físico esté corrupto
Corrupt block relative dba: 0x00c0b317 (file 3, block 45847)
Fractured block found during dbv: 
Data in bad block:
 type: 6 format: 2 rdba: 0x00c0b317
 last change scn: 0x0009.5a58966b seq: 0x1 flg: 0x06
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0x00000000
 check value in block header: 0x5708
 computed block checksum: 0x48fd

La página 45849 está marcada como corrupta
Corrupt block relative dba: 0x00c0b319 (file 3, block 45849)
Completely zero block found during dbv: 

La página 45850 está marcada como corrupta
Corrupt block relative dba: 0x00c0b31a (file 3, block 45850)
Completely zero block found during dbv: 
.
.
.
.
.
.

La página 117911 es de entrada - probablemente el medio físico esté corrupto
Corrupt block relative dba: 0x00c1cc97 (file 3, block 117911)
Fractured block found during dbv: 
Data in bad block:
 type: 0 format: 0 rdba: 0x00000000
 last change scn: 0x0000.00000000 seq: 0x0 flg: 0x00
 spare1: 0x0 spare2: 0x0 spare3: 0x0
 consistency value in tail: 0xc90c0601
 check value in block header: 0x0
 block checksum disabled

DBVERIFY - Verificación terminada
Total de Páginas Examinadas     : 141312
Total de Páginas Procesadas (Datos): 41849
Total de Páginas con Fallos (Datos): 0
Total de Páginas Procesadas (Índice): 46801
Total de Páginas con Fallos (Índice): 0
Total de Páginas Procesadas (LOB)  : 3100
Total de Páginas con Fallos (LOB)  : 0
Total de Páginas Procesadas (Otras): 27154
Total de Páginas Procesadas (Seg): 0
Total de Páginas con Fallos (Seg): 0
Total de Páginas Vacías         : 22352
Total de Páginas Marcadas como Corruptas: 56
Total de Páginas de Entrada     : 6
Total de Páginas Cifradas        : 0
SCN de Bloque Superior            : 1961026953 (9.1961026953)

Con esto tendremos también la información en la vista v$database_block_corruption;, pero ¿que objetos son los que tenemos con problemas?
Si ejecutáis la consulta :

set linesize 200
set pagesize 200
SELECT e.owner, e.segment_type, e.segment_name, e.partition_name, c.file#
, greatest(e.block_id, c.block#) corr_start_block#
, least(e.block_id+e.blocks-1, c.block#+c.blocks-1) corr_end_block#
, least(e.block_id+e.blocks-1, c.block#+c.blocks-1)
- greatest(e.block_id, c.block#) + 1 blocks_corrupted
, null description
FROM dba_extents e, v$database_block_corruption c
WHERE e.file_id = c.file#
AND e.block_id <= c.block# + c.blocks - 1
AND e.block_id + e.blocks - 1 >= c.block#
UNION
SELECT s.owner, s.segment_type, s.segment_name, s.partition_name, c.file#
, header_block corr_start_block#
, header_block corr_end_block#
, 1 blocks_corrupted
, 'Segment Header' description
FROM dba_segments s, v$database_block_corruption c
WHERE s.header_file = c.file#
AND s.header_block between c.block# and c.block# + c.blocks - 1
UNION
SELECT null owner, null segment_type, null segment_name, null partition_name, c.file#
, greatest(f.block_id, c.block#) corr_start_block#
, least(f.block_id+f.blocks-1, c.block#+c.blocks-1) corr_end_block#
, least(f.block_id+f.blocks-1, c.block#+c.blocks-1)
- greatest(f.block_id, c.block#) + 1 blocks_corrupted
, 'Free Block' description
FROM dba_free_space f, v$database_block_corruption c
WHERE f.file_id = c.file#
AND f.block_id <= c.block# + c.blocks - 1
AND f.block_id + f.blocks - 1 >= c.block#
order by file#, corr_start_block#;

Obtendréis un resultado similar a este


OWNER        SEGMENT_TYPE       SEGMENT_NAME                   PARTITION_NAME   CORR_START_BLOCK# CORR_END_BLOCK# BLOCKS_CORRUPTED DESCRIPTION
----------- ------------------ ------------------------------------------------- ---------- ----------------- ---
SYS           TABLE              WRH$_PGASTAT                       3             45847         45847                1
SYSMAN        TABLE              MGMT_TARGET_ASSOC_ERROR            3             45851          45851             1 Segment Header

Como siempre, tenemos mas información y mas precisa en soporte oracle en :

  • OERR: ORA-1578 «ORACLE data block corrupted (file # %s, block # %s)» Master Note [ID 1578.1]
  • Note 28814.1 Handling Oracle Block Corruptions in Oracle7/8/8i/9i/10g
  • Note 556733.1 DBMS_REPAIR script y Note 68013.1 DBMS_REPAIR example
  • Physical and Logical Block Corruptions. All you wanted to know about it. [ID 840978.1]

Problemas con glibc-devel instalando OEM 12c (crt1.o)

Hoy vamos a ver la solución a un problema en la instalación de OEM 12c bajo Oracle linux 6.4

Si miramos la documentación de la instalación en el apartado de paquetes tenemos que necesitamos los paquetes:

  • glibc-devel-2.5-49-i686 (This is a 32-bit package)
  • glibc-devel-2.5-49-x86_64 (This is a 64-bit package)

Sin embargo, si miramos lo que tenemos en la distribución,

[root@emc ~]# rpm -qa --queryformat "%{NAME}-%{VERSION}-%{RELEASE}(%{ARCH})\n" | grep glibc-dev
glibc-devel-2.12-1.107.el6(x86_64)

Y a la hora de instalar otro glibc-devel nos dice que ya está instalado

[root@emc ~]# yum install glibc-devel-2.12-1.80.el6
Loaded plugins: security
Setting up Install Process
Package matching glibc-devel-2.12-1.80.el6.x86_64 already installed. Checking for update.
Nothing to do

Si intentamos instalar , llega aun punto en que nos da un error de linkado, y es que no encuentra la librería crt1.o


INFO: Salida final del proceso iniciado.
INFO: ----------------------------------
INFO: Excepción devuelta de la acción: make
Nombre de la Excepción: MakefileException
Cadena de la Excepción: Error al llamar al destino 'install' del archivo make '/oem/oem12c/oms/sqlplus/lib/ins_sqlplus.mk'. 
Consulte '/oraInventory/logs/installActions-XX.log' para obtener más información.
Gravedad de la Excepción: 1
INFO: POPUP WARNING:Error al llamar al destino 'install' del archivo make '/oem/oem12c/oms/sqlplus/lib/ins_sqlplus.mk'. Consulte '/oraInventory/logs/installActions-XX.log' para obtener más información.

Haga clic en  "Reintentar" para volver a intentarlo.
Haga clic en "Ignorar" para ignorar este error y continuar.
Haga clic en "Cancelar" para parar esta instalación.

Este error estaba en el proceso de linkado delsqlplus, con el error

/usr/bin/ld: crt1.o: No suxh file or directory

La solución es tremendamente sencilla, y pasa un poco por la comprension del Oracle Linux, y es que,debemos instalar una librería del formato i396 (i696 para Oracle Linux), el problema , es que, cuando ejecutamos el yum este no instala las librerias de i686 debido a que nuestro sistema es x64.

Así pues, hay que forzarle a que instale el paquete de i386 (i686) con el comando


yum install glibc-devel.i686

Con este comando, tendremos los dos paquetes instalados

[root@emc ~]# rpm -qa --queryformat "%{NAME}-%{VERSION}-%{RELEASE}(%{ARCH})\n" 
 | grep glibc-dev

glibc-devel-2.12-1.107.el6(x86_64)
glibc-devel-2.12-1.107.el6(i686)

Y la instalación continuará sin problemas

Encontrar el proceso que se come la CPU en windows

Una de las principales diferencias de oracle para Unix y Windows radica en que, debido a el tipo de sistema operativo, en Windows tenemos un proceso monolítico oracle.exe, y no la multitud de procesos que nos encontramos en los sistemas Unix. Así pues, cuando queremos saber cual es el proceso que se nos come la CPU, siempre vamos a tener una misma respuesta oracle.exe y, además de eso, probablemente no podamos enlazarlo con los procesos de sistema operativo.

¿Como solucionamos este problema?

Para empezar, mi recomendación es tener en el servidor uno de estos dos programas

  • Pprocess explorer
  • QSlice

Los dos programas son gratuitos y se pueden descargar desde soporte de microsoft, y nos permitirán ver con mayor facilidad el origen de nuestro problema.

Si abrimos el process explorer , veremos algo similar a esto:
process explorer

Aquí podemos ver como uno de los procesos oracle se esta comiendo el 100% de la CPU , si hacemos boton derecho «propiedades», el process explorer nos indicará en una ventana independiente la informacion de este proceso, si vamos a la pestaña «threads» y ordenamos por CPU, tendremos:
proceso oralce.exe

Aqui vemos como los treads que mas CPU están consumiendo son

  • 3076 con el 23%
  • 4976 con el 19,95%

Ahora, teniendo estos dos número de thread, si que podremos ir a nuestra ventana de sql y enlazar este numero de thread con el proceso/sesion de Oracle que está causando la carga


select proc.spid ThreadNO,  
sess.username Usuario,  
sess.osuser OSUser,
sess.machine Maquina,  
sess.status Estado,  
sess.sid SessionID,  
sess.program Program  
from v$process proc, v$session sess, v$bgprocess bg  
where sess.paddr = proc.addr  
and bg.paddr(+) = proc.addr  
and proc.spid in (3076)

Esta informacion tambien puede obtenerse con qslice.exe, solamente que la información del thread está en exadecimal, y habremos de pasarla a decimal, por otra parte, la ventaja del qslice.exe es que es más ligero que el process explorer, con lo que, como decía al principio, mi recomendación es tener los dos en el servidor