martes, 11 de agosto de 2015

ERROR ACFS AL EJECUTAR SCRIPT ROOT.SH EN INSTALACIÓN GRID INFRAESTRUCTURE

Que tal amigos!

Durante la instalación de 'Grid Infraestructure' en RAC versión 11.2.0.4 en Linux-Suse 11 sp3, se llegó a la etapa donde es necesario ejecutar los siguientes scripts con el usuario 'root':


El script 'orainstRoot.sh' se ejecutó correctamente. Al ejecutar el script 'root.sh',  se recibió el siguiente error, abortándose la instalación.

‘can not startup ACFS services’

El error hace referencia al ‘Oracle Automatic Storage Management Cluster File System’ (ó ACFS por sus siglas en inglés). Es un software que extiende las capacidades del ‘ASM’ para el almacenamiento de archivos que se encuentran fuera de la base de datos, principalmente información de tipo semi-estructurada y no estructurada.  En nuestro caso no requeríamos el ‘ACFS’,  sin embargo, se incluye en la instalación por default.
                                                                                                                                                       
Iniciamos la búsqueda del error en ‘Oracle Support’  (que en ocasiones parece ser más labor de detective forense que de informático..) encontrando la nota ‘Doc ID 1638529.1’ con el siguiente mensaje:

‘11.2.0.4.0 Cluster Grid Infrastructure Installation On SLES 11 SP3 Fails With [ACFS-9109: oracleoks.ko driver failed to load]’               

La nota de Oracle nos indica como ‘síntoma’ el siguiente:

‘Grid Infrastructure (11.2.0.4) Clusterware installation on SLES 11 SP3 is failing during the root.sh execution’

Esta nota nos envía a una matriz de certificación de ‘ACFS’ para todos los sistemas operativos en el siguiente documento:

‘ACFS Support On OS Platforms (Certification Matrix). (Doc ID 1369107.1)’

En la matriz de certificación de ‘ACFS’ para Novell Oracle-Suse 11 Sp3 nos muestra dos 'bugs' existentes y su respectivo parche. Todo indica que vamos a requerir un parche ....

Base Bugs (17428148, 17475946) + Patch: 18143006)

El parche ‘18143006’ resuelve diferentes ‘bugs’. El número 17475946  con la leyenda ‘ROOT.SH OR ACFSROOT INSTALL, FAILS: ACFS-9109: SLES11 SP3’ parece ser el relacionado con nuestro problema .

Bugs Resolved by This Patch
17070158             NODE CRASHED WHILE MOUNTING ACFS
17164243             KERNEL PANIC[ORACLEADVM+23DC8] WHEN STOP CRS
17172303             CRASHES HAPPENS WHEN A MKNOD IS USED IN A NFSV4/ACFS FILESYSTEM
17203009             11204GI+11204RAC WITH OH ON ACFS, COREDUMPING ON CLEAN
17363999             BUILD FAILURE FOR USM_11.2.0.4.0_NT_130818
17376318             IOCTL OFSCTL_GETLOG, RETURNS TOO MUCH DATA AND ACFSUTIL CORE DUMPS
17428148             ACFS DRIVER CANNOT INSTALL ON SLES11 SP2: 3.0.80-0.7-DEFAULT
17475946             ROOT.SH OR ACFSROOT INSTALL, FAILS: ACFS-9109: SLES11 SP3
17611362             CREATE SNAP AND RESIZE OPERATION NOT MAKE PROGRESS
17699423             ACFS HUNG ON OFSACQUIRERESOURCELITE_OSD

Descargamos el archivo  'p181430006_112042forACFS_Linux-x86-64.zip'Para aplicar este parche es necesario crear un archivo de respuesta o ‘response file’, el cual viene especificado en la nota ‘Doc ID 966023.1’. El parche fue descargado de la siguiente liga:


Previo a la ejecución del parche es necesario descargar la utilería ‘opatch’. Es importante validar que el directorio ‘OPatch’ se encuentre generado sobre el ‘Home Directory’ del ‘GRID’:

/u01/app/oracle/11.2.0/grid> echo $ORACLE_HOME
/u02/app/oracle/product/11.2.0/db_1

/u01/app/oracle/11.2.0/grid/OPatch


Una vez generado el directorio ‘OPatch’ en la ruta correcta  y descargada la versión requerida del ‘OPatch’, en este caso la 11.2.0.3.6 , se valida  con el comando ‘opatch lsinventory’:

/u01/app/oracle/11.2.0/grid/OPatch> ./opatch lsinventory
Oracle Interim Patch Installer version 11.2.0.3.6
Copyright (c) 2013, Oracle Corporation.  All rights reserved.

Se descompacta el archivo 'p181430006_112042forACFS_Linux-x86-64.zip' generandose el directorio 18143006  y  los archivos bundle.xml, README.html y README.txt

El siguiente paso es generar un archivo de respuesta o ‘response file’ que será utilizado más adelante en la aplicación del parche de ‘ACFS’, con la siguiente sintaxis:

$ORACLE_HOME/OPatch/ocm/bin/emocmrsp –no_banner –output /u01/app/oracle/file.rsp



Una vez generado el ‘response file’ file.rsp’ se ejecuta el siguiente comando para la aplicación del parche 18143006:

./opatch auto p18143006_112042forACFS_Linux-x86.64 –oh /u01/app/oracle/11.2.0/grid -ocmrf /u01/app/oracle/file.rsp


Donde  ‘oh /u01/app/oracle/11.2.0/grid’, es la ruta del ‘Oracle Home’ del ‘grid’ y ‘ocmrf /u01/app/oracle/file.rsp’ es la ubicación del ‘response file’ generado previamente.

Una vez ejecutada la aplicación del parche, este inicia los servicios de ‘ASM’ y ‘CSS’, con lo que la instalación del ‘GRID’ es finalizada.  Este parche debe ejecutarse para instalaciones ‘RAC’ y ‘standalone server’. Como datos curioso, este parche para ‘ACFS’  no es requerido en la versión anterior: 11.2.0.1.

Gracias, saludos!

José Manuel Vizcaíno Culebra

Contacto servicios profesionales

jose.vizcainoculebra@gmail.com


5532439143 Ciudad de México


jueves, 23 de julio de 2015

AGREGANDO DISCOS EN ORACLE RAC 11gr2 CON ASMLIB

Que tal amigos!

Después de realizarse la instalación de un RAC Oracle 11gr2 en plataforma Linux-Suse, recibimos un requerimiento para incrementar el storage de la base de datos productiva. La configuración discos se realizó por medio de las librerías 'asmlib'. Esta son opcionales y únicamente se encuentran disponibles para plataformas Linux.

Durante años la ventaja de utilizar 'ASM' para eliminar la necesidad de utilizar 'filesystems', no fue explotada completamente debido a la práctica muy común entre los administradores de arquitecturas 'SAN' de agrupar los discos en grupo de volúmenes o 'volumen groups' y posteriormente generar particiones o 'logical volumens' que eran asignadas al 'ASM', para que a su vez estas particiones fueran asignadas a 'diskgroups' Oracle.

Por decirlo así, se realizaban grupos de discos a 'nivel Oracle'  sobre los grupos a 'nivel Linux', cuando únicamente deberían existir los 'diskgroups' de Oracle.

Regresando a nuestro ejercicio,  se tienen que adicionar los discos con todos los servicios en línea, incluyendo la base de datos, con los siguientes pasos:

1.- Validación de asmlib activo

En este caso, por ser una adición de discos, ya se tiene configurado el 'asmlib' incluyendo las siguientes librerías, validadas con el comando 'rpm -qa | grep asm'.

#rpm -qa | grep asm
oracleasmlib-2.0.4-1.SLE11
oracleasm-2.0.5-7.37.3               
oracleasm-support-2.1.8-1.SLE11

Todos los comandos de 'asmlib' son ejecutados con el usuario 'root'. Con el siguiente comando validamos que 'asmlib' se encuentre activo previo a la asignación de más de discos:

oracle@l:/rac1>
#/usr/sbin/oracleasm status
Checking if ASM is loaded: yes
Checking if /dev/oracleasm is mounted: yes

Cuando se instala el 'asmlib', automáticamente genera el filesystem 'oracleasmfs' montado sobre la ruta '/dev/oracleasm', el cual puede ser validado con la ejecución del comando df -ha.

Hasta este momento se verificó que se tienen activos todos servicios del 'asmlib'.

2.- Validación de discos  o 'LUNS' de la 'SAN' en ambos nodos

Ahora es momento de validar los nuevos discos. En nuestro caso, los discos que vamos a adicionar con 'asmlib' se encuentran sobre arquitectura 'SAN', en plataforma EMC Symmetric Vmax.

Se nos proporciona la siguiente lista con 6 'discos' o 'LUNS' SAS FC a 15 RPM que deberán ser agregados  utilizando 'asmlib'

emcpowerba
emcpowerbb
emcpowerbc
emcpowerbd
emcpowerbe
emcpowerbf

Estos discos también son conocidos como 'LUNS' o 'Logical Units Number'. Estas son particiones generadas en la misma 'SAN' en una capa anterior al sistema operativo.

X ejemplo: en nuestro caso nos asignaron seis 'LUNS', siendo que a nivel 'SAN' son únicamente dos discos físicos de 150 GB cada uno:

DISCO                                                                    LUN              TAMAÑO X LUN EN GB
--------------------------------------------------------------------------------------------------------------
Disco fisco /dev/sda de 150 GB                             emcpowerba              50
                                                                                emcpowerbb             50
                                                                                emcpowerbc             50
Disco fisco /dev/sdb de 150 GB                              emcpowerbd             50
                                                                                emcpowerbe              50
                                                                                emcpowerbf              50
--------------------------------------------------------------------------------------------------------------
Total discos físicos    300 GB                                 Total Luns                      300 GB


Al final, el sistema operativo va a 'ver' las 'LUNS' como discos físicos y finalmente las 'LUNS' serán asignadas al 'asmlib'.

El siguiente paso es validar si podemos 'ver' las 'LUNS' por medio del comando 'ls -l'. El listado nos muestra las 'LUNS' del rango 'ba' a 'bf'. La nomenclatura 'emcpower' nos indica que se tienen dos canales de fibra óptica por cada disco físico, para fines de redundancia. El software de 'EMC' llamado 'power path' es el encargado de manejar este tipo de configuración.

Ejecución del comando 'ls -l' ejecutado en el nodo uno:
   
root@rac1:>ls -l /dev/emcpowerb*
brw-rw---- 1 root disk 120,  832 Jul 17 17:40 /dev/emcpowerba
brw-rw---- 1 root disk 120,  848 Jul 17 17:40 /dev/emcpowerbb
brw-rw---- 1 root disk 120,  864 Jul 17 17:40 /dev/emcpowerbc
brw-rw---- 1 root disk 120,  880 Jul 17 17:40 /dev/emcpowerbd
brw-rw---- 1 root disk 120,  896 Jul 17 17:40 /dev/emcpowerbe
brw-rw---- 1 root disk 120,  912 Jul 17 17:40 /dev/emcpowerbf

Ejecución del comando 'ls -l' ejecutado en el nodo dos, donde se valida que están utilizando los mismos discos que en él nodo uno.

root@rac2:>ls -l /dev/emcpowerb*
brw-rw---- 1 root disk 120,  832 Jul 17 17:38 /dev/emcpowerba
brw-rw---- 1 root disk 120,  848 Jul 17 17:38 /dev/emcpowerbb
brw-rw---- 1 root disk 120,  864 Jul 17 17:38 /dev/emcpowerbc
brw-rw---- 1 root disk 120,  880 Jul 17 17:38 /dev/emcpowerbd
brw-rw---- 1 root disk 120,  896 Jul 17 17:38 /dev/emcpowerbe
brw-rw---- 1 root disk 120,  912 Jul 17 17:40 /dev/emcpowerbf

3.- Particionamiento de los discos con 'fdisk' únicamente en el nodo uno del RAC

El siguiente paso es particionar las seis 'LUNS' con el comando 'fdisk'. Este se realizara únicamente en el nodo uno del 'RAC'. En este punto es importante no particionar por error una de las 'LUNS' ya existentes y asignadas al 'ASM'.  En las opciones 'First Sector' y 'Last sector' se va a teclear 'enter' para que tome por default el tamaño completo de la 'LUN' en una sola partición de tipo 'primary'. El siguiente ejemplo muestra el particionamiento de la 'LUN' '/dev/emcpowerba'

fdisk /dev/emcpowerba
Command (m for help): u
Changing display/entry units to sectors
Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First sector (61-1048575, default 61):
Last sector or +size or +sizeM or +sizeK (2048-5048575, default 5048575):
Using default value 5048575                   
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
Syncing disks.

El comando 'fdisk' nos va a generar el archivo '/dev/emcpowerba1', el cual va a ser asignado al 'asmlib':

root@lnx:/rac1> ls -l emcpowerba*
brw-rw---- 1 root disk 120,  832 Jul 17 17:40 emcpowerba
brw-rw---- 1 root disk 120,  833 Jul 17 17:40 emcpowerba1

Es conveniente validar la partición generada con el comando 'fdisk -l', donde podemos visualizar en la columna 'Device Boot' la partición generada:

rac1:~ # fdisk -l /dev/emcpowerba

Disk /dev/emcpowerba: 53.7 GB, 53687746560 bytes
40 heads, 32 sectors/track, 81921 cylinders, total 104858880 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xfff072fe

Device Boot       Start         End      Blocks    Id  System
/dev/emcpowerba1  2048     104858879    52428416   83  Linux

Este procedimiento se va a ejecutar sobre las seis 'LUNS' asignadas. Si ejecutamos el comando 'fdisk -l /dev/emcpowerba' en el nodo dos del 'RAC', nos indicara que no existe la partición. Más adelante el comando '#usr/sbin/oracleasm scandisks' se encarga de actualizar las particiones en el nodo dos.

4.- Ejecución del comando 'createdisk' con 'asmlib'

Con el usuario 'root' vamos a ejecutar el comando de 'asmlib''createdisk' para etiquetar las particiones de las 'LUNS' previamente generadas únicamente en el nodo uno.

root@rac1>
 #/usr/sbin/oracleasm createdisk DGDAT07 /dev/emcpowerba1
#/usr/sbin/oracleasm createdisk DGDAT08 /dev/emcpowerbb1
#/usr/sbin/oracleasm createdisk DGDAT09 /dev/emcpowerbc1
#/usr/sbin/oracleasm createdisk DGDAT010 /dev/emcpowerbd1
#/usr/sbin/oracleasm createdisk DGDAT011 /dev/emcpowerbe1
#/usr/sbin/oracleasm createdisk DGDAT012 /dev/emcpowerbf1
   
5.- Ejecución del comando '#/usr/sbin/oracleasm listdisks' en el nodo uno.

EL comando 'listdisks' nos va a desplegar los discos generados por 'asmlib', incluyendo los discos etiquetados anteriormente:

root@rac1>
#/usr/sbin/oracleasm listdisks  
DGDAT01
DGDAT02
DGDAT03
DGDAT04
DGDAT05
DGDAT06
DGDAT07
DGDAT08
DGDAT09
DGDAT010
DGDAT011
DGDAT012

6.- Ejecución del comando '/usr/sbin/oracleasm scandisks' únicamente en el nodo dos

En este caso NO fue requerida la ejecución del comando '/sbin/partprobe' para actualización de la tabla de particiones.  Ejecutamos el comando '/usr/sbin/oracleasm scandisks' en el nodo dos:

root@rac2>
#/usr/sbin/oracleasm scandisks

Reloading disk partitions: done
Cleaning any stale ASM disks ...
Scanning system for ASM disks ...
Instantiating disk "DGDAT07"
Instantiating disk "DGDAT08"
Instantiating disk "DGDAT09"
Instantiating disk "DGDAT010"
Instantiating disk "DGDAT011"
Instantiating disk "DGDAT012"

Una vez finalizada la ejecución del comando, en el mismo nodo dos, validamos que se encuentren accesibles los nuevos discos etiquetados por 'asmlib':

 #/usr/sbin/oracleasm listdisks  
DGDAT01
DGDAT02
DGDAT03
DGDAT04
DGDAT05
DGDAT06
DGDAT07
DGDAT08
DGDAT09
DGDAT010
DGDAT011
DGDAT012

El comando 'fdisk -l /dev/emcpowerba' ejecutado en él nodo dos, nos mostrara la particiones, ya que el comando'/usr/sbin/oracleasm scandisks' se encargó de actualizar la tabla de particiones sin necesidad de reiniciar los dos nodos de Linux.

7.- Adicionar los discos al diskgroup DATA

Una vez validados los discos en ambos nodos del clúster, ingresamos con él usuario ‘grid’, con las variables de ambiente para conectarse a la instancia de ‘ASM’  en el nodo uno con el comando ‘sqlplus  /as sysasm’ . Generamos el script agregando el prefijo ‘ORCL:’  que Oracle agrega a los discos cuando son configurados por medio de ‘asmlib’.

ALTER DISKGROUP DATA ADD DISK             
'ORCL: DGDAT07',
'ORCL: DGDAT08',
'ORCL: DGDAT09',
'ORCL: DGDAT010',
'ORCL: DGDAT011’,
'ORCL: DGDAT012'
REBALANCE POWER 10;

Monitoreamos la ejecución por medio de la vista ‘gv$asm_operation’,  donde nos muestra un estimado de 10 minutos para efectuar el rebalanceo de discos

SQL> select group_number, operation, state, est_minutes, inst_id from gv$asm_operation;

GROUP_NUMBER  OPERATION   STATE    EST_MINUTES    INST_ID
---------------------  ---------------   -------    -----------------     ----------
           1                             REBAL            RUN            10                          1
           1                             REBAL            WAIT                                         2


Después de 10 minutos efectuamos nuevamente la consulta, al no retornar registros se da por finalizado el proceso de adición de discos.

SQL> select group_number, operation, state, est_minutes, inst_id from gv$asm_operation;

No rows selected

EL incremento de discos se puede realizar por medio de la utilería ‘asmca’ con la limitante de no poder especificar el grado de rebalanceo.   En él parámetro ‘asm_power_limit’ de la instancia de ‘ASM’ tenemos el valor por default que es 1. Sin embargo, en este caso no limito el grado de rebalanceo utilizado, que fue de 10. 

SQL> show parameter power

NAME                                             TYPE            VALUE
------------------------------------ ----------- ------------------------------
asm_power_limit                      integer            1  

Algunas notas de Oracle nos indican que hay que actualizar el parámetro ‘asm_diskstring’ con el valor de ‘ORCL:*’. En este caso no se actualizó este parámetro.  Después de agregar los discos, se reiniciaron los dos nodos del ‘RAC’ y no se tuvieron problemas para levantar las dos instancias de ‘ASM’, por lo que abra que revisar en detalle las notas de ‘metalink’ para validar su efecto.

SQL> show parameter asm_diskstring

NAME                                                      TYPE        VALUE
------------------------------------ ----------- ------------------------------
asm_diskstring                                   string
  
Conclusiones

El adicionar discos a una configuración ya existente por medio de ‘asmlib’ presenta algunas ventajas: 
  • Persistencia de discos.  Los discos utilizados por ‘ASM’ tendrán un nombre fijo, sin importar cuantas veces se reinicien los equipos.
  •  No es necesario utilizar ‘discovery path’ ya que de forma automática se detectan los discos.
  • No es requerido cambiar los dueños de los discos a nivel sistema operativo, con chown oracle:oinstall.
  • La opción ‘scandisks’ facilita la actualización de tabla de particiones en ambientes ‘RAC’.
  • A pesar de la ‘persistencia’ de los discos, el reinicio de los servidores se realiza en tiempos aceptables.


 Saludos!

José Manuel Vizcaíno Culebra

Contacto servicios profesionales

jose.vizcainoculebra@gmail.com

5532439143 Ciudad de México.



jueves, 26 de febrero de 2015

ERROR ORA-04030 MEMORIA DE PROCESO INSUFICIENTE EN AIX

Que tal amigos!

Realizamos la instalación de Oracle 11.2.0.4 sobre plataforma AIX 1.7.  La base de datos se configuró para ser de tipo 'Datawarehouse'. En un inicio los usuarios no reportaron problemas, sin embargo, después de un mes de operaciones, se presento el siguiente error:


"ORA-04030: memoria de proceso insuficiente al intentar asignar 246296 bytes (QERGH hash-agg,kllcqas:kllsltba)
04030. 00000 -  "out of process memory when trying to allocate %s bytes (%s,%s)"
*Cause:    Operating system process private memory has been exhausted
*Action: "

Después de ejecutar el asistente 'Automatic Workload Repository' o 'AWR' se detectó un sentencia que realizaba consultas 'anidadas'  del tipo 'select campo, (select campo),' donde al final se realizaba un 'join' entre el resultado de estas subconsultas.  La sentencia realiza un 'full scan' y join de tipo 'hash' el cual utilizaba memoria privada o 'Private Global Area'  o 'PGA'. 

Todo indicaba que el origen del problema era  por memoria 'PGA' insuficiente, como lo indica el error '  Operating system process private memory has been exhausted' .   Al parecer la solución era muy sencilla: incrementar el tamaño de la 'PGA'.

Verificamos el tamaño actual de la memoria 'PGA', donde se valida que se tienen 10 GB asignados:

SQL> show parameter pga_aggregate_target

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target                 big integer 10G

Para validar si los 10gb de 'PGA'  son suficientes, ejecutamos una consulta sobre la vista 'pga_target_for_estimate' para validar cual es la recomendación de Oracle respecto al tamaño ideal. El 'advisor' de Oracle nos indica que un incremento mayor a los 12 GB, no representa un diminución de las lecturas a disco, por lo que el valor actual de 10gb es cercano al ideal.

SQL>SELECT PGA_TARGET_FOR_ESTIMATE/1024/1024/1024, ESTD_EXTRA_BYTES_RW/1024/1024/1024 FROM v$pga_target_advice
     ORDER BY 1;
       2
PGA_TARGET_FOR_ESTIMATE/1024/1024/1024 ESTD_EXTRA_BYTES_RW/1024/1024/1024
-------------------------------------- ----------------------------------
                                  1.25                         604.720174
                                   2.5                          604.713353
                                     5                           604.713353
                                   7.5                          604.713353
                                    10                         485.791062
                                    12                         473.302542
                                    14                         473.302542

Validamos si las consultas están consumiendo más de los 10gb asignados, por medio de la vista 'v$process'. Para nuestra sorpresa, verificamos que el máximo de 'PGA' en uso es de apenas 446 mb.


SELECT sum(pga_used_mem)/1024/1024, sum(pga_max_mem)/1024/1024 FROM v$process;

SUM(PGA_USED_MEM)/1024/1024 SUM(PGA_MAX_MEM)/1024/1024
--------------------------- --------------------------
                 446.813904                 877.627762


Ejecutamos una consulta en la vista 'v$pgastat'  y nos confirma el dato: apenas .4 gb de memoria en uso. Queda claro que no es un problema de memoria insuficiente en la 'PGA', por lo que en este momento tenemos más dudas que respuestas.

 SQL>   select name, value/1024/1024/1024 from v$pgastat where name = 'total PGA inuse';

NAME                                                             VALUE/1024/1024/1024
---------------------------------------------------------------- --------------------
total PGA inuse                                                            .440420151

Algunas notas en Internet nos indican que 'seguramente' es un problema de parámetros de 'kernel' del sistema operativo 'AIX'. Modificamos los valores a 'unlimited', reiniciamos la instancia de Oracle, ejecutamos nuevamente la consulta y el error ora-04030 ... se sigue presentando!

$ ulimit -a 
time(seconds) unlimited 
file(blocks) unlimited 
data(kbytes) unlimited 
stack(kbytes) unlimited 
memory(kbytes) unlimited 
coredump(blocks) unlimited 
nofiles(descriptors) unlimited 
threads(per process) unlimited 
processes(per user) unlimited 

Otra nota en Internet nos indica que la modificación del siguiente parámetro relacionado a accesos de tipo ´hash' es la solución a nuestro query problemático.  Aplicamos el 'alter system', ejecutamos el query y el error ora-04030 .... continúa ...

alter system set "_gby_hash_aggregation_enabled"=false scope=both;


Verficando el log '/u01/app/oracle/diag/rdbms/DWH/dwh/incident/incdir_120150'  por medio de la utilería 'adrci', nos muestra que, al parecer esta asignando segmentos de 111 MB en él ´HEAP MEMORY'


PRIVATE HEAP SUMMARY DUMP
111 MB total:
   108 MB commented, 594 KB permanent
  2819 KB free (0 KB in empty extents),
      74 MB,   1 heap:    "session heap   "            2188 KB free held
      30 MB,   2 heaps:   "callheap       "            130 KB free held 


Parece ser que Oracle está asignando segmentos de memoria muy pequeños. Según una nota del 'metalink' esto puede ser corregido con el siguiente parámetro del 'init.ora. Aplicamos el cambio, reiniciamos y la instancia ... y el error continúa!

ALTER SYSTEM SET "_use_realfree_heap"=false scope=spfile; 

Se empieza a escuchar entre los usuarios la frase temida por todo DBA .. 'traigan un experto ..'.  En vista del éxito obtenido, se levanta un 'service 'request'. Soporte de Oracle  nos solicita revisar el documento 'Doc ID 1260095.1'  relacionado al siguiente 'bug':

'11gR2/Aix - Dedicated Server Processes Have Large Usla Heap Segments Compared To Older Versions'

La nota de Oracle nos envía directamente al sitio de IBM donde se explica que es un ´bug'  que se presenta únicamente en plataforma 'AIX'. Oracle e IBM tuvieron que trabajar en conjunto para desarrollar una serie de parches, tanto a nivel operativo  como a nivel base de datos para solucionar este problema:

'Many customers have noted increased per-process memory consumption for the "USLA heap" segment with Oracle 11gR2. USLA stands for User-Space Loader Assistant and “heap” is an area of memory used for dynamic memory allocation. To fully resolve this, IBM and Oracle have collaborated to develop, test and release AIX enhancements and Oracle patches that reduce memory use to levels close to those previously experienced. 

 Nos solicitan verificar si tenemos instalados los siguientes parches  o 'APARS' a nivel sistema operativo :

AIX 7.1 TL-01 APAR IV09541, IV28925, IV21116 

El detalle de los parches para AIX se puede validar en las siguientes ligas:

http://www-01.ibm.com/support/docview.wss?uid=isg1IV28925 
http://www-01.ibm.com/support/docview.wss?uid=isg1IV21116 
http://www-01.ibm.com/support/docview.wss?uid=isg1IV09541 

Validando los parches de AIX ,  el comando 'instfix' solo nos muestra el parche 'APAR' IV09541 como instalado. La gente de soporte de sistema operatívo nos asegura que los parches faltantes ya están incluídos por ser un 'release' de AIX más nuevo.

Soporte de Oracle nos solicita instalar el siguiente parche desarrollado exclusivamente para la solución del problema de memoria en AIX:

Patch 10190759

Aplicamos el parche 10190759 con la utilería 'opatch'. Reiniciamos el servidor. Los usuarios empiezan a probar y el error de memoria se presenta de una forma esporádica, por lo que soporte de Oracle nos solicita realiza algunos ajustes en la sentencia de alto consumo de 'PGA'. Actualmente la instancia funciona de forma normal y no se ha vuelto a presentar el error ORA 04030, que se negaba a morir.

Gracias, saludos!

José Manuel Vizcaíno Culebra

Contacto servicios profesionales:

jose.vizcainoculebra@gmail.com

5532439143 CDMX


viernes, 13 de junio de 2014

UN VISTAZO A LA NUEVA VERSIÓN DE BASE DE DATOS ORACLE: 12C

Que tal amigos!


La recien liberada versión Oracle 12c nos ofrece una nueva arquitectura: 'MULTITENANT DATABASE'.

Un ejemplo común en Internet de este tipo de arquitectura es la de un tren. Con la arquitectura tradicional de Oracle tendriamos una locomotora  con un vagon de carga enganchado o 'conectado'. Si vamos a agregar un vagón, tendriamos que conseguir otra locomotora para conectar el nuevo vagón. Al final tendriamos dos locomotoras, cada una arrastrando su propio vagón.

En la arquitectura 'MULTITENANT' tendriamos una sola locomotora arrastrando los dos vagones. La locomotora principal vendria siendo el 'CONTAINER DATABASE' y los vagones serían las 'PLUGGABLES DATABASE'. La memoria 'PGA', 'SGA'  y  los procesos de 'BACKGROUND' como 'PMON' y 'SMON' únicamente va residir en el 'CONTAINER DATABASE'.

Si generamos la base de datos con el asistente 'DBCA' de Oracle con la opción 'MULTITENAT' tendriamos la siguiente arquitectura:

  1. Una base de datos 'CONTAINER DATABASE ' generada automáticamente por Oracle identificada con el nombre CDB$ROOT'
  2. Una base de datos 'PLUGGABLE DATABASE' generada  por Oracle para uso interno del  manejador, conocida como base de datos 'sembrada'  identificada con el nombre 'PDB$SEED'.  Esta se encuentra en modo 'READ ONLY' y es utilizada como un 'template'  por parte del manejador para generar  nuevas bases de datos 'PLUGGABLES'.
  3. Una (o más)  'PLUGGABLE DATABASE' donde van a residir los datos de los aplicativos. Por ejemplo si vamos a tener una base de datos para un aplicativo 'CRM' tendriamos la base 'PDBCRM' y otra 'PDBDWH' para un Datawarehouse.
Del diccionario de datos de Oracle compuesto por las vistas  'DBA_' ,'USER_' , y 'ALL_', habra que familiarizarse un nuevo grupo de vistas identificadas con el prefijo 'CDB_'.  En estas últimas podremos visualizar los objetos residentes tanto en el 'CONTAINER' como en las bases de datos  'PLUGGABLES'.

En versiones anteriores a Oracle 12c,  debiamos realizar una consulta a la tabla 'DBA_TABLES'  de cada instancia de Oracle para conocer el total de tablas. En 12c, con una consulta a la tabla 'CDB_TABLES' podremos conocer las tablas de cada base de datos identificadas con una nueva columna :  'CON_ID' que nos va indicar en que base nos encontramos. Por default, Oracle asigna los siguientes valores a la columna 'CON_ID'

  • Valor de 0 según la documentación de Oracle incluye tanto el 'container' como las base de datos no 'container.
  • Valor de 1  para el container 'CDB$ROOT'
  • Valor de 2 para la base de datos 'sembrada' o 'PDB$SEED'
  • Valor de 3 o más para las bases de datos donde van a residir la información de aplicativos
Si requerimos el nombre de todas las tablas de los diferentes aplicativos, lo realizariamos con un 'SELECT table_name FROM cdb_tables where CON_ID>2',  sin necesidad de utilizar un viejo conocido : el  'export ORACLE_SID=id_instancia'  requerido para cambiarse de instancia.

Cuando ingresamos a una configuración tipo 'MULTITENANT', por default nos va a posicionar en la base de datos contenedor o 'CONTAINER DATABASE', lo cual podemos verificar con el siguiente comando desde sqlplus :

SQL> show con_name

          
           CON_NAME 
    _________________
    
           CDB$ROOT

Si deseamos conectarnos a la base de datos de tipo 'pluggable' llamada  'pdborcl' , es necesario ejecutar la siguiente sentencia:

 SQL> ALTER SESSION SET CONTAINER=PDBORCL;

             Session altered
  
La base de datos contenedor o 'CDB$ROOT' contiene su propio 'system' y 'sysaux'.  Un aspecto curioso, es que los tablespaces 'undo' y 'temp' que contienen los datos para todas las 'pluggables databases',  van a residir en la base de datos contenedor. Aunque es la configuración  por default, puede ser modificada.

De la misma forma, solo van a existir los 'redo logs' únicamente en el contenedor, por lo que podriamos tener transacciones de diferentes bases de datos concentrados en estos. Sería interesante validar en un futuro, si esto no va a provocar problemas de contención en disco. El archivo de control o 'control file' únicamente va a existir en la base de datos contenedor.

Las 'pluggable databases' van a tener sus propios tablespaces 'system' , 'sysaux' y de datos. Se puede conocer su estatus por medio de la siguiente consulta a la vista dinámica 'v$pdbs':

 SQL> SELECT name, open_mode FROM v$pdbs;

  NAME                             OPEN_MODE
 --------------------------        ----------------
 PDB$SEED                       READ ONLY
 PDBORCL                        READ WRITE

Por medio de la siguiente consulta podemos conocer que parámetros son modificables a nivel 'pluggable database'.

SQL> SELECT substr(NAME,1,30), substr(value,1,30) FROM V$SYSTEM_PARAMETER
   where ISPDB_MODIFIABLE ='TRUE'
      ORDER BY NAME;


Adicionalmente,  sera obligado familiarizarnos con el 'package' : 'dbms_resource_manager' para modificar parámetros de las 'pluggables databases'.

En versiones anteriores a 12c,  cuando requeriamos clonar una base de datos a un ambiente diferente, utilizabamos el comando 'ALTER DATABASE BACKUP CONTROLFILE TO TRACE AS .....'.  que contenia principalmente la lista de 'redo logs' y 'datafiles' de la base a clonar, no importando que esta se encontrara en estado 'OPEN'.

En 12c,  ya no podremos utilizar este comando para clonar, ya que las 'pluggable databases' no tienen 'control file' !! ... únicamente se tiene el 'control file' para la base de datos 'CONTAINER'.  Para exportar la definición de la 'pluggable database'  es necesario que esta se encuentre en modo read only:

  SQL> alter database open read only;

La definición de la 'pluggable database'  se exporta en formato 'XML' con el siguiente comando:

SQL> BEGIN
         DBMS_PDB.DESCRIBE(
            pdb_descr_file => 'c:\orcl\pdborcl.xml');
        END;
    /


Otra forma de exportar la metada a un archivo 'XML ' es por medio del siguiente comando:

SQL> ALTER PLUGGABLE DATABASE pdborcl UNPLUG INTO 'C:\orcl\pdborcl.xml';

Pluggable database altered.

Sin embargo hay que ser cuidadosos con él comando 'UNPLUG', ya que una vez ejecutado,   no es posible realizar ningún operación sobre la 'pluggable database'.  Si queremos dar de baja  la base 'pdborcl' recien 'desconectada' nos va a enviar el siguiente mensaje:

SQL> shutdown immediate
ORA-65086: no se puede abrir/cerrar la base de datos de conexi¾n


De la misma forma no podemos abrir la base de datos:

SQL> startup
ORA-65086: no se puede abrir/cerrar la base de datos de conexi¾n


Si ejecutamos el comando 'UNPLUG' y resulta que realmente no deseabamos 'desconectar' la base de datos y queremos realizar un 'PLUG IN', de la base de datos, veremos que al parecer no existe o no es necesario un comando para realizarlo la 're-conexión.'  

Para volver a regenerar la base de datos 'pdborcl' en el mismo 'container' donde realizamos el 'unplug', tenemos que borrar la base de datos 'pdborcl', teniendo cuidado de no borrar los 'datafiles', con el siguiente comando:

SQL> DROP PLUGGABLE DATABASE pdborcl  KEEP DATAFILES;

Pluggable database dropped.

Con el siguiente comando recreamos las base de datos 'pdborcl' a partir de la metadata contenida en el archivo 'pdborcl.xml', con lo que ya tendriamos disponible nuevamente la base de datos 'pdborcl'

SQL>CREATE PLUGGABLE DATABASE pdborcl USING  'C:\orcl\pdborcl.xml'  COPY TEMPFILE REUSE;

Pluggable database created.

En 12c clonar una base de datos 'pluggable' dentro de la misma instancia es mucho más rápido y sencillo que en versiones anteriores.  Vamos a clonar la base de datos 'pdborcl' a una nueva llamada 'pdbventas' utilizando la opción 'FILE_NAME_CONVERT'.  Esta claúsula funciona por pares, es decir los 'datafiles' contenidos en el directorio de la base de datos origen  'c:\pdborcl1\' van a ser copiados al directorio de la base destino o clonado  'c:\pdbventas1\'.   Con el siguiente comando creamos la nueva base de datos 'pdbventas' en apenas unos segundos.

SQL> CREATE PLUGGABLE DATABASE PDBVENTAS FROM PDBORCL
           FILE_NAME_CONVERT =('c:\pdborcl1\', 'c:\pdbventas1\');

Pluggable database created.
 

Si por ejemplo intentamos clonar sin especificar su par para el directorio 'c:\pdborcl2\', recibimos el siguiente mensaje 

SQL> CREATE PLUGGABLE DATABASE PDBROCL FROM PDBVENTAS FILE_NAME_CONVERT
           =('c:\pdborcl1\', 'c:\pdbventas1\', 'c:\pdborcl2\' );

         CREATE PLUGGABLE DATABASE PDVENTAS FROM PDBORCL FILE_NAME_CONVERT =('c:\pdborcl1\', 'c:\pdbventas1\', 'c:\pdborcl2\' );
                                                                              
    *
ERROR at line 1:
ORA-02000: falta la palabra clave ,

Con esto finalizamos un pequeño vistazo a esta nueva versión. Habra que familiarizarse con nuevos comandos para clonar, crear, respaldar y recuperar base de datos en 12c.

Conclusiones

La nueva funcionalidad 'MULTITENAT' es una de las más atractivas de la nueva versión Oracle 12c. Permite optimizar el uso de recursos, al eliminar la necesidad de tener varias instancias en un solo equipo. La generación de nuevas bases de datos es un proceso mucho más rápido y sencillo que en versiones anteriores. 

Se podrá tener un control centralizado de las diferentes bases de datos a partir de un contenedor principal. La administración de usuarios tambien observa cambios,  ya que tendremos usuarios comunes o 'common users' , consolidación de esquemas  o 'schema consolidation'.  Se tendrán también reubicación de 'datafiles' en línea,  una nueva infraestructura para 'RAC' llamada 'Flex Cluster' , alta redundancia para la instancia de 'ASM'  llamda 'Flex ASM',  tener más de un índice sobre una misma columna, entre otras nuevas funcionalidades.

Saludos !

José Manuel Vizcaíno Culebra

Contacto servicios profesionales:

jose.vizcainoculebra@gmail.com

5532439143 Ciudad de México

miércoles, 21 de mayo de 2014

CUANDO LOS LOBS AFECTAN EL DESEMPEÑO DE LA BASE DE DATOS


Hola amigos !

El siguiente caso  (que no pretende ser una guía para la reubicación de LOBS)  fue originado por el llamado de un cliente reportando  problemas de lentitud de una base de datos Oracle 11.1.0.7 en configuración 'RAC' de cuatro nodos, con un aplicativo 'Oracle Business Process Management' operando en ambiente productivo. La primera actividad fue la obtención de un reporte de rendimiento por medio de la utilería 'AWR'  ejecutando el script 'awrrpti.sql' por cada nodo del cluster. 

Una vez generado el reporte, en la sección 'Top 5 Timed Foreground Events' del 'AWR' nos aparecio el evento 'enq HW -contention'  en todos los nodos del cluster, el cual no es muy común en este tipo de reportes: (solo muestro el top de un nodo)

Top 5 Timed Foreground Events

Event                                     Waits          Time(s)           Avg wait (ms)       %DB time    Wait Class

enq HW -contention           586,913         14,728                 25                        45.61       Configuration
db file sequential read      1,272,487          5,816                   5                        18.01        User I/O
DB CPU                                                         4,442                                            13.69
enq TX - row lock cont         3,973            1,310                330                         4.06        Application
direct path read                  948,724               943                    1                         2.92         User I/O

El evento 'enq HW -contention' nos hace referencia  a la 'marca de agua' o 'high water mark', la cual indica al manejador en que punto existen bloques libres y usados en un segmento de datos.  Que este evento aparezca en el 'Top 5'  indica que existe  un alto número de actualizaciones en algún segmento.  La nota Doc ID 9801919.8 de 'metalink' nos indica lo siguiente:

            "enq: HW - contention" may be seen for segments that have heavy  concurrency
              and often need to add an extent due to repeated SEG$ updates of dictionary data" 

Otras notas de 'metalink' nos sugieren que puede existir un problema con actualizaciones en campos tipo 'LOBs' (Large Objects) que contienen información no estructurada como archivos, imagenes o 'XMLs' entre otros.  Continuamos con  la búsqueda del ´culpable' de este evento en los 'tops' de las sentencias 'SQL'  en el reporte 'AWR'

En la sección 'sqls ordenados por tiempo de ejecución' nos aparece en primer lugar un 'UPDATE' sobre la tabla 'PPROCINSTANCE' el cual de forma notable ocupa el 75.91% del tiempo de la base de datos (por cuestiones de formato no incluí todas las columnas del 'AWR')

Elapsed Time(s)  CPU Time(s)   Executions   %Total DB Time     SQL text

  24,247                  1,259              84,911              75.91                        UPDATE PPROCINSTANCE SET .....
    1,832                     109              12,881                 5.74                        INSERT INTO PPROCINSTANCE ....

Continuamos en la sección 'sql ordenados por tiempo de CPU requerido'  y nuevamente aparece la sentencia 'UPDATE'  sobre la tabla 'PPROCINSTANCE':

CPU Time(s)   Elapsed Time(s)    %Total   %Total DB Time         SQL text

   1,259                 24,247                  34.20             75.91                       UPDATE PPROCINSTANCE SET ..
      174                      624                     4.73                1.95                      SELECT PPROCESSID, INSTID.... 

En la sección 'sql  ordenados por accesos a memoria' el 'UPDATE' de la tabla 'PPROCINSTANCE' aparece nuevamente

Buffer Gets      Gets per Exec   %Total     CPU Time (s)         SQL text

37,273,368          3,727.34             31.60        113.22                    DELETE FROM PCORRELATION ...
35,175,421             414.26             29.82      1259.44                    UPDATE PPROCINSTANCE SET ....

La sentencia tiene condiciones para los campos 'processid', 'instid' y 'threadid'. Sospechamos que puede existir un 'full scan'. Sin embargo, al revisar el 'explain plan'  se valida que el acceso es vía índice (aqui les debo el explain plan :-( )

     UPDATE pprocinstance SET (varios campos)..WHERE processid= ? AND instid= ? AND threadid=?

Para obtener el 'explain plan' sin necesidad de ejecutar nuevamente la sentencia, es muy útil el 'package' 'dbms_xplan.display_awr'.  Con el  'id query' obtenido en el reporte  'AWR'  se agrega como parámetro (en este caso el id 'g1jx24n27sykx' ) en el llamado del ´package'.

     SELECT plan_table_output FROM table (dbms_xplan.display_awr('g1jx24n27sykx'));

El siguiente paso es verificar si existe un 'LOB' en la tabla PPROCINSTANCE por medio de una consulta a la tabla  'DBA_LOBS'.   Identificamos al 'LOB'  'SYS_LOB0000108088C00003$$'  

     SELECT SUBSTR(table_name,1,40),  SUBSTR(segment_name, 1,30) ,  SUBSTR(tablespace_name,  1,30) 
           FROM dba_lobs 
       WHERE table_name = 'PPROCINSTANCE'
  
     SUBSTR(TABLE_NAME,1,40)                SUBSTR(SEGMENT_NAME,1,30)     SUBSTR(TABLESPACE_NAME,1,30)
       -------------------------------------------------       ------------------------------------------------    ---------------------------------------------------
          PPROCINSTANCE                                  SYS_LOB0000108088C00003$$                      USERS
Ahora que conocemos el segmento tipo 'LOB',  vamos a buscar en el reporte 'AWR' para validar si realmente tiene un impacto en el desempeño de la base de datos. En la sección de 'segmentos con más lecturas a disco' aparece el 'LOB'  de la tabla  PPROCINSTANCE con el 78% del total !

             Object Name                                               Obj. Type    Physical Writes    %Total DB Time   

           SYS_LOB0000108088C00003$$            LOB               993, 397                    73.40 
           SYS_LOB0000108088C00008$$            LOB                  31,622                      2.34 


Verificamos que índices tiene la tabla 'PPROCINSTANCE'  con la siguiente consulta. La tabla tiene tres índices que se encuentran en el tablespace 'USERS' que es el mismo que el utilizado por el 'LOB'.

            SELECT SUBSTR(index_name, 1,20), substr(tablespace_name,1,30) FROM dba_indexes
               WHERE table_name = 'PPROCINSTANCE';

             SUBSTR(INDEX_NAME,1,          SUBSTR(TABLESPACE_NAME,1,30)
            -------------------------------------          ------------------------------------------------
                   INSTPART                                                   USERS

                   ACT                                                               USERS
                   ASSIGPART                                                USERS

Ahora validamos el tablespace por default para la tabla PPROCINSTANCE  y no resulta una sorpresa que también sea USERS. Por alguna razón,  se generaron los datos, índices y lobs de la tabla maestra PPROCINSTANCE en el mismo tablespace, lo que genera problemas de contención.

          SELECT tablespace_name FROM dba_tables WHERE table_name = 'PPROCINSTANCE';

                  TABLESPACE_NAME
                  ------------------------------
                          USERS


La guía de Oracle 'Performance Tuning for Oracle Business Process Management Suite 10g' nos recomienda utilizar tablespaces independientes para los segmentos 'LOBS':



                     ' Use Separate Tablespaces for BLOBs If you are storing large
                        BLOBs in the database, you should consider a separate
                        tablespaces for the BLOBs'


Platicando con el cliente, le comentamos la necesidad de particionar la tabla y distribuirla en diferentes tablespaces. El regenerar la tabla PPROCINSTANCE impacta al resto del modelo de datos, implicando la recompilación de todos los objetos relacionados como stored procedures y packages entre otros. Por ser ambiente productivo, el cliente no desea que la tabla se vuelva a generar. Nos da como opción redistribuirla en diferentes tablespaces, pero sin regenerar ningún objeto. 

Para redistribuir la tabla PPROCINSTANCE se van a a generar tres tablespaces: para datos, índices y uno dedicado al segmento 'LOB'

                   CREATE TABLESPACE TBS_DATOS_PROC DATAFILE  '+BDBPMDATA' size 2048M;  
                   CREATE TABLESPACE TBS_IND_PROC DATAFILE   '+BDBPMINDEX' size 2048M;       
                   CREATE TABLESPACE TBS_LOBS_PROC DATAFILE  '+BDBPMLOG' size 10,000M   

Previo al proceso de reubicación es recomendable un 'full backup' de la base de datos y generar un listado que contenga el estatus de todos los objetos de la base de datos con la siguiente sentencia:

              SELECT object_name, object_status FROM dba_objects;

Una vez generados los tablespaces dedicados a la tabla PPROCINSTANCE es necesario reubicar los datos con la  siguiente secuencia :
  1. Reubicar los datos de la tabla al tablespace 'TBS_DATOS_PROC'
  2. Reubicar los índices de la tabla TBS_IND_PROC  al tablespace TBS_IND_PROC'
  3. Reubicar el 'LOB'  ubicado en el campo INSTANCEDATA al tablespace TBS_LOBS_PROC
  4. Reconstruir los índices inválidos
Ejecutamos el primer paso al reubicar los datos  de la tabla al tablespace 'TBS_DATOS_PROC'. Este paso va a invalidar todos los índices asociados a la tabla.
           ALTER TABLE OBPMENGORDERS.PPROCINSTANCE MOVE TABLESPACE TBS_DATOS_PROC;
 Continuamos con el segundo paso que es reubicar los índices al nuevo tablespace 'TBS_IND_PROC':
           ALTER INDEX OBPMENGORDERS.INSTPART REBUILD TABLESPACE TBS_IND_PROC;
              ALTER INDEX OBPMENGORDERS.ACT REBUILD TABLESPACE TBS_IND_PROC;
              ALTER INDEX OBPMENGORDERS.ASSIGPART REBUILD TABLESPACE TBS_IND_PRO;
Realizamos la etapa de reubicación del lob del campo INSTANCEDATA.  Por ser únicamente un campo el reubicado, no podemos utilizar la opción  'MOVE TABLESPACE'. Utilizaremos la opción 'MOVE LOB' indicando el campo a mover. Esta opción es la más lenta de todas, por lo que si se desea realizar una reubicación de 'LOBS', es recomendable realizar una prueba en ambiente pre-productivo para calcular ventanas de tiempo para el mantenimiento.
   ALTER TABLE OBPMENGORDERS.PPROCINSTANCE                                                                                                                                               MOVE LOB(INSTANCEDATA) STORE AS (TABLESPACE TBS_LOBS_PROC);

En caso de que el campo 'LOB'  a reubicar sea del tipo 'XML Type',  se puede utilizar el siguiente comando
donde se incluye la sentencia 'XMLDATA'

 ALTER TABLE xxxxxx move lob (CAMPO.XMLDATA) store as (TABLESPACE tablespace_destino);
Procedemos a  reconstruir los índices inválidados de la tabla PPROCINSTANCE

           ALTER INDEX OBPMENGORDERS.INSTPART REBUILD;

               ALTER INDEX OBPMENGORDERS.ACT REBUILD;

               ALTER INDEX OBPMENGORDERS.ASSIGPART REBUILD;

Por último volvemos a ejecutar el query para validar los objetos de la base de datos, asi como su estatus, que debe coincidir con el conteo previo a la reubicación.

              SELECT object_name, object_status FROM dba_objects;

Una vez que el conteo  es el correcto, finalizamos la reubicación.

Conclusiones

En el caso de tablas que contenga campos tipo 'LOB' y observan un elevado número de actualizaciones, es recomendable generar 'tablespaces' en discos independientes para reducir la contención y de ser posible generar la tabla particionada.  Se puede programar el uso de la sentencia 'alter table xxx shrink space compact' para reclamar el espacio eliminado.  Si se genero la tabla y ya cuenta con información, se puede realizar la reubicación por medio de la opción 'MOVE LOB', sin embargo hay que tener en cuenta los tiempos requeridos con esta opción.

José Manuel Vizcaíno Culebra

Contacto servicios profesionales:

jose.vizcainoculebra@gmail.com

5532439143 Ciudad de México