Version del parcheado de la base de datos

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

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

Oracle 11g

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

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

Lo que nos devolvera algo similar a :

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

Oracle 12c

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

Preguntando a DBA_REGISTRY_SQLPATCH

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



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

Lo que nos devolvera algo similar a

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

Mediante el package dbms_qopatch

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

 
 set serverout on
exec dbms_qopatch.get_sqlpatch_status;

Lo que nos devuelve

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

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

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

Renombrado un ASM diskgroup

Hoy vamos a ver una entrada muy rapida sobre como renombrar un diskgroup exsistente en ASM.

Lo primero que tenemos que tener en cuenta es que , deberemos de parar todas las bases de datos que esten escribiendo sobre ese diskgroup.

Para nuestro caso hemos creado un grupo llamado WRONG_DATA01


test1.pamplona.name:oracle  crsctl stat res -t
--------------------------------------------------------------------------------
Name           Target  State        Server                   State details
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.LISTENER.lsnr
               ONLINE  ONLINE       test1                STABLE
ora.WRONG_DATA01.dg
               OFFLINE OFFLINE      test1                STABLE
ora.test1_FRA_01.dg
               OFFLINE OFFLINE      test1                STABLE
ora.test1_REDO_01.dg
               ONLINE  OFFLINE      test1                STABLE
ora.test1_REDO_02.dg
               OFFLINE OFFLINE      test1                STABLE
ora.asm
               ONLINE  OFFLINE      test1                Instance Shutdown,STARTING
ora.ons
               OFFLINE OFFLINE      test1                STABLE
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.cssd
      1        ONLINE  ONLINE       test1                STABLE
ora.diskmon
      1        OFFLINE OFFLINE                               STABLE
ora.evmd
      1        ONLINE  INTERMEDIATE test1                STABLE
--------------------------------------------------------------------------------

Lo primero y mas logico, es que deberemos de desmontar el dislkgroup a renombrar

test1.pamplona.name:oracle  srvctl stop  diskgroup -diskgroup WRONG_DATA01

test1.pamplona.name:oracle  crsctl stat res -t
--------------------------------------------------------------------------------
Name           Target  State        Server                   State details
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.LISTENER.lsnr
               ONLINE  ONLINE       test1                STABLE
ora.WRONG_DATA01.dg
               OFFLINE OFFLINE      test1                STABLE
ora.test1_FRA_01.dg
               ONLINE  ONLINE       test1                STABLE
ora.test1_REDO_01.dg
               ONLINE  ONLINE       test1                STABLE
ora.test1_REDO_02.dg
               ONLINE  ONLINE       test1                STABLE
ora.asm
               ONLINE  ONLINE       test1                Started,STABLE
ora.ons
               OFFLINE OFFLINE      test1                STABLE
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.cssd
      1        ONLINE  ONLINE       test1                STABLE
ora.diskmon
      1        OFFLINE OFFLINE                               STABLE
ora.evmd
      1        ONLINE  ONLINE       test1                STABLE
--------------------------------------------------------------------------------

Una vez desmontado, procedermos a renombrarlo.
EL renombrado cuenta con dos fases

  • Fase 1 : Esta fase solamente genera el fichero de configuracion
  • Fase 2 Basandose en la fase uno lleva a cabo el cambio .

Veamos a cabo como se lleva a cabo.

Fase 1

A pesar de ser la fase 1 la llamaremos como phase=both y añadiremos el flag check=true , esto nos asegura que no llevara a cabo cambios en las cabeceras de los discos ASM .

renamedg phase=both dgname=WRONG_DATA01 newdgname=test1_DATA_01 asm_diskstring=’/dev/oracleasm/disks/’ check=true verbose=true

test1.pamplona.name:oracle  renamedg phase=both dgname=WRONG_DATA01 newdgname=test1_DATA_01 asm_diskstring='/dev/oracleasm/disks/' check=true verbose=true
Parsing parameters..
Parameters in effect:

         Old DG name       : WRONG_DATA01
         New DG name          : test1_DATA_01
         Phases               :
                 Phase 1
                 Phase 2
         Discovery str        : /dev/oracleasm/disks/
         Check              : TRUE
         Clean              : TRUE
         Raw only           : TRUE
renamedg operation: phase=both dgname=WRONG_DATA01 newdgname=test1_DATA_01 asm_diskstring=/dev/oracleasm/disks/ check=true verbose=true
Executing phase 1
Discovering the group
Performing discovery with string:/dev/oracleasm/disks/
Identified disk UFS:/dev/oracleasm/disks/test1_DATA_01_0001 with disk number:0 and timestamp (33066256 1704307712)
Identified disk UFS:/dev/oracleasm/disks/test1_DATA_01_0002 with disk number:1 and timestamp (33066256 1704307712)
Checking for hearbeat...
Re-discovering the group
Performing discovery with string:/dev/oracleasm/disks/
Identified disk UFS:/dev/oracleasm/disks/test1_DATA_01_0001 with disk number:0 and timestamp (33066256 1704307712)
Identified disk UFS:/dev/oracleasm/disks/test1_DATA_01_0002 with disk number:1 and timestamp (33066256 1704307712)
Checking if the diskgroup is mounted or used by CSS
Checking disk number:0
Checking disk number:1
Generating configuration file..
Completed phase 1
Executing phase 2
Looking for /dev/oracleasm/disks/test1_DATA_01_0001
Leaving the header unchanged
Looking for /dev/oracleasm/disks/test1_DATA_01_0002
Leaving the header unchanged
Completed phase 2
Terminating kgfd context 0x7fb9d6aff0a0

Esta fase nos habra dejado un fichero de configuracion llamado renamedg_config

Fase 2

Este es el comendo que realmente nos llevara a cabo el cambio


renamedg phase=two dgname=WRONG_DATA01 newdgname=test1_DATA_01 asm_diskstring=’/dev/oracleasm/disks/’ verbose=true config=’./renamedg_config’

importanteComo podeis ver es muy sencillo, pero es muy importante tener en cuenta que, este cambio solo se lleva a cabo a nivel de sistema operativo y ASM , no a nivel de ficheros de configuracion o de base de datos, por lo que tendreis que revisar:

  • Ubicacion de pfiles y spfiles
  • Ubicacion de controlfiles dentro de los ficheros de arranque
  • Ubicacion de ficheros de base datos (datafiles,tempfiles, redologs)

Parametro oculto _query_on_physical

Hoy vamos a ver una de estas entradas que contradicen algunas otras que podemos ver en internet.

Dado lo restrictivo de Oracle con el licenciamiento, seria muy interesante contar con una opcion que nos deshabilitara el Real-Time Query del Dataguard .
Si buscamos por internet, nos encontramos con un parametro oculto llamado _query_on_physical

Si Ejecutamos el comando

alter system set "_query_on_physical"=false scope=spfile;

Deshabilitaremos el Active Dataguard, pero … ¿que dice Oracle de todo esto?
Oracle como siempre dice que nunca debemos de activar parametros ocultos en la base de datos a no ser que sea especificamente recomendado por el equipo de soporte

NOTE: Hidden parameter «_query_on_physical» is NOT an option to prevent Active Data Guard usage. It should NOT be used at all in any version of the Oracle Database.
It is unsupported to be set unless Oracle Support advises it for diagnostic reason

Asi que, ya sabeis, la unica opcion que nos da Oracle para no activarlo es «tener cuidado».

Como siempre, mas informacion en soporte:

  • Which are Supported Methods to Prevent Active Data Guard Usage When License is Not Available? (Doc ID 2269239.1)

kernel.panic_on_oops : Nuevo parametro de la 12c

Hoy vamos a ver otra de estas pequeñas sorpresas de Oracle en las nuevas versiones
En los requisitos de la instalacion de la version 12c de Oracle nos encontramos con la siguiente nota

Note: 
The below Kernel Parameter "panic_on_oops=1" is being Introduced and required
 from 12.1.0.2.0 onwards.
kernel.panic_on_oops=1

Que es lo que hace este parametro del Kernel?
Este parametro simplemente controla el comportamiento del kernec cuando un oops or bug es detectado.

Los valores que puede tomar es:

  • 0: INtenta continuar la operacion
  • 1: Entra en panic , ademas de este panica, si el sysctl es distnto de cero, entonces el servidor se reiniciara

Como veis, un parametro bastante inocuo… hasta que buscamos la causa de por que el servidor se ha reiniciado

Consultas basicas para lob segments

Hoy vamos a otra de estas entradas para dummies que recopilan SQL utles, en este caso para tratar con los lobs.
Las variables de formateo del sqlplus para estas consultas serian

set linesize 180 pagesize 900
column SEGMENT_NAME format a40;
column TABLE_NAME format a60;
column TABLESPACE_NAME format a30;
column owner format a20;

Lista de los lobs mas grandes y lo que ocupan para el esquema

select  e.owner,l.tablespace_name,
l.table_name,
l.segment_name,sum(e.bytes/(1024*1024*1024)) Gb
from dba_extents e,dba_lobs  l
where
	e.owner = l.owner
	and 	e.segment_name = l.segment_name
	and 	e.OWNER='ESQUEMA'
	and 	e.segment_type = 'LOBSEGMENT'
     group by  
     e.owner,l.tablespace_name,
    l.table_name,
     l.segment_name 
     order by Gb desc ;

Obtener los datos (esquema,tabla y columna) de un LOB determinado

select OWNER,TABLE_NAME,COLUMN_NAME from dba_lobs
 where SEGMENT_NAME='SYS_LOBXXXXXX$$';

Bytes ocupados por un LOB

select sum(dbms_lob.getlength (COLUMNA))/1024/1024 Mb ESQUEMA.TABLA;
o bien 

select bytes/1024/1024 Mb
from dba_segments where segment_name ='SYS_LOBXXXXXX$$' ;

o esta mas completa

set serveroutput on
declare
     l_segment_size_blocks NUMBER;
     l_segment_size_bytes NUMBER;
     l_used_blocks NUMBER;
     l_used_bytes NUMBER;
     l_expired_blocks NUMBER;
     l_expired_bytes NUMBER;
     l_unexpired_blocks NUMBER;
     l_unexpired_bytes NUMBER;
     l_unused_blocks NUMBER;
     l_unused_bytes NUMBER;
     l_non_data_blocks NUMBER;
     l_non_data_bytes NUMBER;
 BEGIN
	DBMS_SPACE.SPACE_USAGE(
   	  segment_owner =>'ESQUEMA',
	  segment_name => 'SYS_LOB0000227238C00034$$',
	  segment_type => 'LOB',
	  segment_size_blocks => l_segment_size_blocks,
	  segment_size_bytes => l_segment_size_bytes,
	  used_blocks => l_used_blocks,
	  used_bytes => l_used_bytes,
	  expired_blocks => l_expired_blocks,
	  expired_bytes => l_expired_bytes,
	  unexpired_blocks => l_unexpired_blocks,
	  unexpired_bytes => l_unexpired_bytes
           );
      l_unused_blocks := l_segment_size_blocks - (l_used_blocks + l_expired_blocks + l_unexpired_blocks);
      l_unused_bytes := l_segment_size_bytes - (l_used_bytes + l_expired_bytes + l_unexpired_bytes);
	  l_non_data_blocks := l_unused_blocks + l_expired_blocks + l_unexpired_blocks;
	  l_non_data_bytes :=  l_unused_bytes + l_expired_bytes + l_unexpired_bytes;
	  DBMS_OUTPUT.ENABLE;
	   DBMS_OUTPUT.PUT_LINE(' Segment Blocks/Bytes   = '||l_segment_size_blocks||' / '||l_segment_size_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Unused Blocks/Bytes    = '||l_unused_blocks||' / '||l_unused_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Used Blocks/Bytes      = '||l_used_blocks||' / '||l_used_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Expired Blocks/Bytes   = '||l_expired_blocks||' / '||l_expired_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Unexpired Blocks/Bytes = '||l_unexpired_blocks||' / '||l_unexpired_bytes);
	  DBMS_OUTPUT.PUT_LINE('===========================================================================');
	  DBMS_OUTPUT.PUT_LINE(' NON Data Blocks/Bytes  = '||l_non_data_blocks||' / '||l_non_data_bytes);
 END;
 /

Mover una tabla con Lobs ( para hacer shrink)

Este metodo implica bloqueo durante el traslado

ALTER TABLE ESQUEMA.TABLA MOVETABLESPACE NUEVOTABLESPACE;
Y para cada uno de los lobs de la tabla 

ALTER TABLE ESQUEMA.TABLA MOVE LOB(COLUMNA) STORE AS SECUREFILE (TABLESPACE NUEVOTABLESPACE);