Describiremos los pasos reales en la migración a Oracle 11g GridInfraestructure a partir de una instalación Oracle RAC 10g, a partir de la idea de migración del post: http://www.soportedba.com/2011/12/oracle-rac-migracion-rapida-10g-11g.html
Estos pasos también servirían por ejemplo, si ocurre una catástrofe en el RAC antiguo y se pierden todos los nodos y backups (quedando sólo el acceso al almacenamiento).
Pasos básicos para el upgrade de la bbdd: http://onlineappsdba.com/index.php/2009/01/22/upgrade-oracle-database-10g-to-11g-r1-111x/
Antes
de la migración se debe “registrar” la bbdd en el RAC, para ello
simulamos la creación de una bbdd en otro grupo de discos FRA por
ejemplo, con el mismo nombre , para posteriormente cambiar directamente el spfile y los recursos asociados, aunque se podría hacer de otra forma, registrando bien los recursos ...
Se hace el switch del init de la bbdd "initdbmaq1.ora" por el antigo pfile
(cambiando varios parámetros como cluster_database=no,
compatible=11.1.0, eliminar user_dump_dest, backgroup_dump..., etc)
En el proceso de migración, el “catupgrd.sql” se obtiene el error:
TO_NUMBER(value$) != (SELECT tz_version from registry$database))
*
ERROR at line 6:
ORA-00942: table or view does not exist
Que
se evitaría habiendo lanzado los pasos previos (motor de la 10g
ejecutando el utlu112i.sql) pero como no lo hicimos, lo que se hace es
eliminar la comprobación del TZ_VERSION del script que llama el
catupgrd.sql que se llama “catupstr.sql”, parece que el proceso de
migración avanza correctamente, aunque está claro que podrá haber
corrupción en datos almacenados con Timezone o similar.
Ejecución del script upgrade principal correcta:
@?/rdbms/admin/catupgrd.sql
Tras la ejecución de los últimos scripts:
@?/rdbms/admin/utlu112s.sql
@?/rdbms/admin/catuppst.sql
@?/rdbms/admin/utlrp.sql
Todo correcto y todo compilado.
Ahora cambiamos el init para que se utilice el +DATA
create spfile=’+DATA’ from pfile;
ponemos en los initdbmaqX.ora :
SPFILE=’+DATA/DBMAQ/initdbmaq.ora’
Todo arranca y funciona correctamente.
Para deregistrar el spfile y que tenga en cuenta el grupo DATA, (en otro caso, en los arranque se sustituye automáticamente el init* por los de la preinstalación previa apuntando al FRA)
srvctl modify database -d dbmaq -p ' ' -a "DATA,FRA"
(ver http://oraganism.wordpress.com/2010/01/02/srvctl-p-option/)
Arracamos el dbconsole:
emctl start dbconsole
Aparece un error que evita podamos acceder, recreamos la key:
emctl config emkey -repos -force
Todo correcto, el acceso a los datos correcto, el acceso al EM Database Control correcto.
domingo, 11 de diciembre de 2011
miércoles, 7 de diciembre de 2011
ACFS (error “ADVM/ACFS is not supported on ...")
Mensaje de error tras instalación grid (en ejecución de root.sh)
"ADVM/ACFS is not supported on centos-release-5-6.el5.centos.1"
Para resolverlo, se cambian los ficheros "/etc/issue", "redhar-release", ....
http://ivan.kartik.sk/oracle/install_ora11gR2_elinux.html
http://brianbontrager.blogspot.com/2009/09/learning-asm-breakin-rules-or-running.html
Con esta última guia se consigue instalar ACFS para Centos, teniendo presente el tipo de instalación x86 o x86_64:
mkdir /lib/modules/2.6.18-128.el5/extra/usm
cp /u01/app/oragrid/product/11.2.0/grid/install/usm/EL5/i386/2.6.18-8/2.6.18-8.el5-i686/bin/*ko /lib/modules/2.6.18-128.el5/extra/usm
chmod 744 /lib/modules/2.6.18-128.el5/extra/usm
cd /u01/app/oragrid/product/11.2.0/grid/bin
./acfsdriverstate -orahome /u01/app/oragrid/product/11.2.0/grid version
"ACFS-9205: OS/ADVM,ACFS installed version = 2.6.18-8.el5(i386)/090715.1"
depmod
"ADVM/ACFS is not supported on centos-release-5-6.el5.centos.1"
Para resolverlo, se cambian los ficheros "/etc/issue", "redhar-release", ....
http://ivan.kartik.sk/oracle/install_ora11gR2_elinux.html
http://brianbontrager.blogspot.com/2009/09/learning-asm-breakin-rules-or-running.html
Con esta última guia se consigue instalar ACFS para Centos, teniendo presente el tipo de instalación x86 o x86_64:
mkdir /lib/modules/2.6.18-128.el5/extra/usm
cp /u01/app/oragrid/product/11.2.0/grid/install/usm/EL5/i386/2.6.18-8/2.6.18-8.el5-i686/bin/*ko /lib/modules/2.6.18-128.el5/extra/usm
chmod 744 /lib/modules/2.6.18-128.el5/extra/usm
cd /u01/app/oragrid/product/11.2.0/grid/bin
./acfsdriverstate -orahome /u01/app/oragrid/product/11.2.0/grid version
"ACFS-9205: OS/ADVM,ACFS installed version = 2.6.18-8.el5(i386)/090715.1"
depmod
Oracle RAC (migración rápida 10g a 11g)
Una forma de realizar las migraciones entre Oracle RAC 10g hacia Oracle Grid 11g rápidamente, sería:
1) Se van quitando nodos de un RAC(10g) antiguo y se reinstalan sobre la nueva arquitectura GRID (11g), el sistema debe estar dimensionado de forma que pueda funcionar correctamente con la mitad de nodos.
2) Una vez todo configurado, se apaga el RAC antiguo(antes habrá que ejecutar los scripts de comprobaciones y pre-upgrade indicados por Oracle) y se ponen visibles los discos para el GRID nuevo, se montan los Disk Groups y se arrancan las bbdd en el nuevo (startup migrate, ... y se deberán lanzar los scripts/procedimientos de migración correspondientes), con lo que se consigue un tiempo de corte mínimo.
3) El resto de nodos del RAC antiguo se van reinstalando e introduciendo en el GRID nuevo.
Sólo en el punto 2 sería necesaria la parada (tiempo de upgrade de las bbdd), pero el tiempo sería mínimo si estuviera todo preparado y probado.
Con esta técnica no existe movimiento real de datos, aunque está claro que se deberán tomar todas las medidas de seguridad oportunas (backups previos, backup de configuraciones, etc).
1) Se van quitando nodos de un RAC(10g) antiguo y se reinstalan sobre la nueva arquitectura GRID (11g), el sistema debe estar dimensionado de forma que pueda funcionar correctamente con la mitad de nodos.
2) Una vez todo configurado, se apaga el RAC antiguo(antes habrá que ejecutar los scripts de comprobaciones y pre-upgrade indicados por Oracle) y se ponen visibles los discos para el GRID nuevo, se montan los Disk Groups y se arrancan las bbdd en el nuevo (startup migrate, ... y se deberán lanzar los scripts/procedimientos de migración correspondientes), con lo que se consigue un tiempo de corte mínimo.
3) El resto de nodos del RAC antiguo se van reinstalando e introduciendo en el GRID nuevo.
Sólo en el punto 2 sería necesaria la parada (tiempo de upgrade de las bbdd), pero el tiempo sería mínimo si estuviera todo preparado y probado.
Con esta técnica no existe movimiento real de datos, aunque está claro que se deberán tomar todas las medidas de seguridad oportunas (backups previos, backup de configuraciones, etc).
ASM (comandos amdu y kfed)
Extraído de: http://asmsupportguy.blogspot.com/2011/09/amdu-asm-metadata-dump-utility.html
amdu - ASM Metadata Dump Utility (>=11g)
Comando muy interesante para el análisis de la metadata de discos ASM e incluso extraer los ficheros (datafiles, controlfiles, ...) contenidos en ellos, sin requerir que el Disk Group esté montado o la instancia ASM operativa.
- Extracción del fichero de control del Disk Group DATA :
amdu -diskstring="ORCL:*" -extract DATA.276 -output control.276 -noreport -nodir
- Extracción de un datafile:
amdu -diskstring="ORCL:*" -extract DATA.267 -output NSA_TN_DATA.267 -noreport -nodir
Para saber los nombres de los datafiles, se pueden utilizar comandos ASM (asmcmd) previos, que requieren del montaje de los Disk Groups y disponibilidad de la instancia ASM o se puede utilizar comandos "kfed":
...
for (( i=0; i<256; i++ ))
do
kfed read /dev/oracleasm/disks/DISK2 aun=8 blkn=$i | grep -1 NSA
done
...
Extraído de: http://asmsupportguy.blogspot.com/2010/04/kfed-asm-metadata-editor.html
kfed - ASM Metadata Editor (>=10g)
Comando muy interesante para leer y modificar la metadata de discos ASM, no requiere que el Disk Group esté montado o la instancia ASM operativa.
cd $ORACLE_HOME/rdbms/lib
make -f ins* ikfed
- Comprobación de que la cabecera del disco asm está bien:
kfed read /dev/oracleasm/disks/DISK4
Si se observa kfbh.type=KFBTYP_INVALID , puede indicar que la cabecera del disco asm está dañada.
amdu - ASM Metadata Dump Utility (>=11g)
Comando muy interesante para el análisis de la metadata de discos ASM e incluso extraer los ficheros (datafiles, controlfiles, ...) contenidos en ellos, sin requerir que el Disk Group esté montado o la instancia ASM operativa.
- Extracción del fichero de control del Disk Group DATA :
amdu -diskstring="ORCL:*" -extract DATA.276 -output control.276 -noreport -nodir
- Extracción de un datafile:
amdu -diskstring="ORCL:*" -extract DATA.267 -output NSA_TN_DATA.267 -noreport -nodir
Para saber los nombres de los datafiles, se pueden utilizar comandos ASM (asmcmd) previos, que requieren del montaje de los Disk Groups y disponibilidad de la instancia ASM o se puede utilizar comandos "kfed":
...
for (( i=0; i<256; i++ ))
do
kfed read /dev/oracleasm/disks/DISK2 aun=8 blkn=$i | grep -1 NSA
done
...
Extraído de: http://asmsupportguy.blogspot.com/2010/04/kfed-asm-metadata-editor.html
kfed - ASM Metadata Editor (>=10g)
Comando muy interesante para leer y modificar la metadata de discos ASM, no requiere que el Disk Group esté montado o la instancia ASM operativa.
cd $ORACLE_HOME/rdbms/lib
make -f ins* ikfed
- Comprobación de que la cabecera del disco asm está bien:
kfed read /dev/oracleasm/disks/DISK4
Si se observa kfbh.type=KFBTYP_INVALID , puede indicar que la cabecera del disco asm está dañada.
RedHat / Centos (comando yum)
-- Para la actualización de nuestros linux RedHat / Centos
cd /etc/yum.repos.d
mv ULN-Base.repo ULN-Base.repo.disabled
wget http://public-yum.oracle.com/public-yum-el4.repo
(modificamos el .repo para habilitar la release que nos convenga)
yum clean all
yum update glibc\*
yum update yum\* rpm\* python\*
yum clean all
yum update
reboot
Otras opciones, por ejemplo, la instalación de oracle-validated (para cambios automáticos de parámetros y demás para ejecución de software Oracle)
yum --enablerepo=el4_u7_base install oracle-validated
Si tenemos algún problema con un kernel parcheado, podemos volver a los anteriores editanto el /etc/grub.conf y eligiendo como kernel default de arranque el antiguo 2.6.9.42 u otro.
cd /etc/yum.repos.d
mv ULN-Base.repo ULN-Base.repo.disabled
wget http://public-yum.oracle.com/public-yum-el4.repo
(modificamos el .repo para habilitar la release que nos convenga)
yum clean all
yum update glibc\*
yum update yum\* rpm\* python\*
yum clean all
yum update
reboot
Otras opciones, por ejemplo, la instalación de oracle-validated (para cambios automáticos de parámetros y demás para ejecución de software Oracle)
yum --enablerepo=el4_u7_base install oracle-validated
Si tenemos algún problema con un kernel parcheado, podemos volver a los anteriores editanto el /etc/grub.conf y eligiendo como kernel default de arranque el antiguo 2.6.9.42 u otro.
LVM (Ampliación de espacio en volumen)
-- Ampliación online de espacio en nodo CentOS Virtualizado (vmware) en volumen local "/"
Se amplia el disco virtualizado en 10G más (a través de la interfaz de gestión vmware), y después se aplican comandos típicos de LVM:
vgdisplay --verbose
fdisk /dev/sda (n, 3, intro, intro, t, 8e (partición Linux VM))
partprobe /dev/sda (para crear el dispositivo /dev/sda3)
pvcreate /dev/sda3
vgextend VolGroup00 /dev/sda3
lvextend -L +10G /dev/VolGroup00/LogVol00
ext2online /dev/VolGroup00/LogVol00
Se amplia el disco virtualizado en 10G más (a través de la interfaz de gestión vmware), y después se aplican comandos típicos de LVM:
vgdisplay --verbose
fdisk /dev/sda (n, 3, intro, intro, t, 8e (partición Linux VM))
partprobe /dev/sda (para crear el dispositivo /dev/sda3)
pvcreate /dev/sda3
vgextend VolGroup00 /dev/sda3
lvextend -L +10G /dev/VolGroup00/LogVol00
ext2online /dev/VolGroup00/LogVol00
OEM Grid Control (Despliegue manual de agente)
-- En una instalación virtualizada(vmware ESX) de Oracle RAC 10g (10.2.0.4, almacenamiento iscsi), tenemos un nodo que no tiene el agente oracle instalado:
Instalación de Agente en linux2 (no estaba instalado):
Nos llevamos el directorio agent10g de $ORACLE_HOME/.. hasta linux2 y cambiamos .../config/emd.properties, cambiando la línea linux1 por linux2.
Con esto, al cabo de un tiempo, el Grid detecta el nodo correctamente y se empieza a monitorizar correctamete.
Instalación de Agente en linux2 (no estaba instalado):
Nos llevamos el directorio agent10g de $ORACLE_HOME/.. hasta linux2 y cambiamos .../config/emd.properties, cambiando la línea linux1 por linux2.
Con esto, al cabo de un tiempo, el Grid detecta el nodo correctamente y se empieza a monitorizar correctamete.
Oracle RAC 10g (Error: "no route to host")
-- En una instalación virtualizada(vmware ESX) de Oracle RAC 10g (10.2.0.4, almacenamiento iscsi) tenemos el error "no route to host" de forma aleatoria en los arranques de los nodos, lo que provoca la inaccesibilidad de los mismos, se lista las acciones correctivas para solucionar el problema en esta instalación en particular:
Linux2 no arranca, errores:
iscsi-sfnet:linux2: Connect failed with rc -113: No route to host
iscsi-sfnet:linux2: establish_session failed. Could not connect to target
iscsi-sfnet:linux2: Waiting 1 seconds before next login attempt
Arrancamos en Single User (-S en el grub), cambiamos el permiso de ejecución al fichero /etc/init.d/iscsi y arrancamos normalemnte, consiguiendo acceso.
Comprobamos no hace ping a openfiler1-priv ni openfiler1, se observa ruta 0.0.0.0, la eliminamos:
route del -net 0.0.0.0 (sin exito)
Se reinicia net:
/etc/init.d/network restart
Conectividad recuperada, pero se observan líneas relacionadas con iptables (aunque el servicio está parado), se prueba a eliminar completamente el servicio:
service iptables save
service iptables stop
chkconfig iptables off
rpm -qa|grep iptables
rpm -e -nodeps iptables-x...
Sigue fallando tras otros reinicios.
Finalmente se encuentra el problema, corresponde con la carga de vmware-tools que es posterior al script de S10network:
S19vmware-tools
Se elimina la carga de vmware-tools (rm /etc/rc3.d/S19vmware-tools) y parece que ya no aparece el error "no route to host".
vmware-tools se sigue cargando en el rc2.d, pero no afecta porque lo importante era el "orden" de arranque, que lo último fuera el S10network
Linux2 no arranca, errores:
iscsi-sfnet:linux2: Connect failed with rc -113: No route to host
iscsi-sfnet:linux2: establish_session failed. Could not connect to target
iscsi-sfnet:linux2: Waiting 1 seconds before next login attempt
Arrancamos en Single User (-S en el grub), cambiamos el permiso de ejecución al fichero /etc/init.d/iscsi y arrancamos normalemnte, consiguiendo acceso.
Comprobamos no hace ping a openfiler1-priv ni openfiler1, se observa ruta 0.0.0.0, la eliminamos:
route del -net 0.0.0.0 (sin exito)
Se reinicia net:
/etc/init.d/network restart
Conectividad recuperada, pero se observan líneas relacionadas con iptables (aunque el servicio está parado), se prueba a eliminar completamente el servicio:
service iptables save
service iptables stop
chkconfig iptables off
rpm -qa|grep iptables
rpm -e -nodeps iptables-x...
Sigue fallando tras otros reinicios.
Finalmente se encuentra el problema, corresponde con la carga de vmware-tools que es posterior al script de S10network:
S19vmware-tools
Se elimina la carga de vmware-tools (rm /etc/rc3.d/S19vmware-tools) y parece que ya no aparece el error "no route to host".
vmware-tools se sigue cargando en el rc2.d, pero no afecta porque lo importante era el "orden" de arranque, que lo último fuera el S10network
domingo, 9 de octubre de 2011
Banco de Datos Cloud
Apoyándonos en la tecnología Grid de Oracle hemos diseñado e implantado un Banco de Datos heterogéneo, que da servicio de acceso a bases de datos Oracle en RAC y MySQL en Alta Disponibilidad.
También se puede incluir en este diseño servicios de MS Sqlserver (en cluster o nó) y MySQL en Cluster, todo ello balanceado en forma de servicios que pueden crecer en rendimiento y capacidad símplemente añadiendo más nodos al Banco de Datos.
También se puede incluir en este diseño servicios de MS Sqlserver (en cluster o nó) y MySQL en Cluster, todo ello balanceado en forma de servicios que pueden crecer en rendimiento y capacidad símplemente añadiendo más nodos al Banco de Datos.
martes, 13 de septiembre de 2011
Script - Borrado de Alertas OEM
-- Para evitar problemas de rendimiento sobre las tablas que utiliza OEM y hacer que nuestro entorno OEM quede "limpio" de alertas (por ejemplo si hemos estado haciendo pruebas de funcionalidad, recuperación, etc), se pueden borrar alertas obsoletas haciendo uso del procedimiento DELETE_CURRENT_SEVERITY del paquete EM_SEVERITY:
exec SYSMAN.EM_SEVERITY.DELETE_CURRENT_SEVERITY (target_guid , metric_guid , key_value);
Donde los valores para target_guid, metric_guid, key_value los podemos obtener de SYSMAN.MGMT_CURRENT_SEVERITY
exec SYSMAN.EM_SEVERITY.DELETE_CURRENT_SEVERITY (target_guid , metric_guid , key_value);
Donde los valores para target_guid, metric_guid, key_value los podemos obtener de SYSMAN.MGMT_CURRENT_SEVERITY
miércoles, 7 de septiembre de 2011
Comprobación variables Bind Oracle
-- La vista DBA_HIST_SQLBIND nos muestra los valores actuales de variables bind, almacenadas según el tiempo de retención AWR:
select count(1) from dba_hist_sqlbind where sql_id='acm0qvuazu...'
select count(1) from dba_hist_sqlbind where sql_id='acm0qvuazu...'
domingo, 14 de agosto de 2011
Instalación - Oracle Restart OHASD
-- Notas Oracle Restart OHASD
Hay que revisar scripts de arranque ohasd:
/etc/init.d/init.ohasd run
Este script en particular busca el fichero : "/etc/oracle/scls_scr/curso/oracle/ohasdrun" el valor contenido en él para intentar el "restart" o símplemente no hacer nada "stop", en cuyo caso se queda el init.ohasd en un "sleep 10" continuo (while (true)).
Una vez arranca ohasd, revisar recursos gestionados, si no arrancan todos, lanzar:
$ORA_CRS_HOME/bin/crsctl start resource -all
Hay que revisar scripts de arranque ohasd:
/etc/init.d/init.ohasd run
Este script en particular busca el fichero : "/etc/oracle/scls_scr/curso/oracle/ohasdrun" el valor contenido en él para intentar el "restart" o símplemente no hacer nada "stop", en cuyo caso se queda el init.ohasd en un "sleep 10" continuo (while (true)).
Una vez arranca ohasd, revisar recursos gestionados, si no arrancan todos, lanzar:
$ORA_CRS_HOME/bin/crsctl start resource -all
Instalación - Oracle GRID Infraestructure 11gR2
-- Notas sobre instalación de Oracle GRID Infraestructure 11gR2
Ips - SCAN, para instalación sin hacer uso de los beneficios de SCAN (Single Client Access Name), antes de lanzar la instalación de Oracle GRID, se debe asociar una IP de SCAN en los ficheros /etc/hosts de cada nodo (la misma ip en cada nodo), pero esa IP no debe estar asignada, en otro caso, fallará el instalador con un mensaje indicando que "ya se está utilizando la ip de scan por algún servidor ".
Posterior a la instalación de Oracle GRID Infraestructure, para que funcionen otros instaladores/configuradores, como la configuración de OEM Database Control RAC, se requiere que la ip de SCAN resuelva a alguna IP, (por ejemplo, a alguna de las VIPs de nuestra configuración), es decir, procederemos a cambiar la ip de scan por alguna VIP de nuestra configuración y lanzaremos el instalador/configurador que corresponda.
Ips - SCAN, para instalación sin hacer uso de los beneficios de SCAN (Single Client Access Name), antes de lanzar la instalación de Oracle GRID, se debe asociar una IP de SCAN en los ficheros /etc/hosts de cada nodo (la misma ip en cada nodo), pero esa IP no debe estar asignada, en otro caso, fallará el instalador con un mensaje indicando que "ya se está utilizando la ip de scan por algún servidor ".
Posterior a la instalación de Oracle GRID Infraestructure, para que funcionen otros instaladores/configuradores, como la configuración de OEM Database Control RAC, se requiere que la ip de SCAN resuelva a alguna IP, (por ejemplo, a alguna de las VIPs de nuestra configuración), es decir, procederemos a cambiar la ip de scan por alguna VIP de nuestra configuración y lanzaremos el instalador/configurador que corresponda.
miércoles, 16 de febrero de 2011
Script - Calculo_MD5_Consulta.sql
-- Función para el cálculo MD5 de una consulta pasada como parámetro:
create or replace function hash_sql(l_query varchar2) return varchar2
is
pragma autonomous_transaction;
l_theCursor integer default dbms_sql.open_cursor;
l_columnValue varchar2(32000);
l_status integer;
l_colCnt number := 0;
l_separator varchar2(1);
l_descTbl dbms_sql.desc_tab;
l_i number:=0;
l_data CLOB:='';
l_checksum CLOB:='';
begin
execute immediate 'alter session set nls_date_format=''dd/mm/yyyy hh24:mi:ss'' ';
dbms_sql.parse( l_theCursor, l_query, dbms_sql.native );
dbms_sql.describe_columns( l_theCursor, l_colCnt, l_descTbl );
for i in 1 .. l_colCnt loop
dbms_sql.define_column( l_theCursor, i, l_columnValue, 32000 );
end loop;
l_status := dbms_sql.execute(l_theCursor);
while ( dbms_sql.fetch_rows(l_theCursor) > 0 ) loop
for i in 1 .. l_colCnt loop
dbms_sql.column_value( l_theCursor, i, l_columnValue );
l_i:=i;
l_data:=l_data||trim(TO_CHAR(l_columnValue));
end loop;
end loop;
dbms_sql.close_cursor(l_theCursor);
rollback;
return dbms_crypto.hash( src => l_data, typ=>dbms_crypto.hash_md5 );
exception
when others then
return 'ERROR';
end;
/
-- Llamada:
select hash_sql ('SELECT * FROM tabla where columna='||CHR(39)||'VALOR'||CHR(39)||' order by 1 ') md5 from dual
/
-- Funcionamiento/Restricciones:
A) Se basa en el uso del paquete DBMS_CRYPTO de Oracle (ver > 10g)
B) El cálculo MD5 ser realiza sobre la concatenación de todas las columnas devueltas por la consulta y concatenación fila a fila de los resultados, por ejemplo:
column1 column2
------- -------
a b
a2 b2
La cadena sobre la que se aplica el MD5 sería:
"aba2b2"
C) Cada valor de cada fila / columna se convierte en texto y se eliminan espacio finales e iniciales (TRIM(TO_CHAR(...))
D) El formato para la conversión de datos tipo fecha es: "dd/mm/yyyy hh24:mi:ss"
E) Es importante que las consultas tengan una ordenación (Ej.- "ORDER BY NLSSORT(VAL_ELE_COD, 'NLS_SORT = BINARY')"
create or replace function hash_sql(l_query varchar2) return varchar2
is
pragma autonomous_transaction;
l_theCursor integer default dbms_sql.open_cursor;
l_columnValue varchar2(32000);
l_status integer;
l_colCnt number := 0;
l_separator varchar2(1);
l_descTbl dbms_sql.desc_tab;
l_i number:=0;
l_data CLOB:='';
l_checksum CLOB:='';
begin
execute immediate 'alter session set nls_date_format=''dd/mm/yyyy hh24:mi:ss'' ';
dbms_sql.parse( l_theCursor, l_query, dbms_sql.native );
dbms_sql.describe_columns( l_theCursor, l_colCnt, l_descTbl );
for i in 1 .. l_colCnt loop
dbms_sql.define_column( l_theCursor, i, l_columnValue, 32000 );
end loop;
l_status := dbms_sql.execute(l_theCursor);
while ( dbms_sql.fetch_rows(l_theCursor) > 0 ) loop
for i in 1 .. l_colCnt loop
dbms_sql.column_value( l_theCursor, i, l_columnValue );
l_i:=i;
l_data:=l_data||trim(TO_CHAR(l_columnValue));
end loop;
end loop;
dbms_sql.close_cursor(l_theCursor);
rollback;
return dbms_crypto.hash( src => l_data, typ=>dbms_crypto.hash_md5 );
exception
when others then
return 'ERROR';
end;
/
-- Llamada:
select hash_sql ('SELECT * FROM tabla where columna='||CHR(39)||'VALOR'||CHR(39)||' order by 1 ') md5 from dual
/
-- Funcionamiento/Restricciones:
A) Se basa en el uso del paquete DBMS_CRYPTO de Oracle (ver > 10g)
B) El cálculo MD5 ser realiza sobre la concatenación de todas las columnas devueltas por la consulta y concatenación fila a fila de los resultados, por ejemplo:
column1 column2
------- -------
a b
a2 b2
La cadena sobre la que se aplica el MD5 sería:
"aba2b2"
C) Cada valor de cada fila / columna se convierte en texto y se eliminan espacio finales e iniciales (TRIM(TO_CHAR(...))
D) El formato para la conversión de datos tipo fecha es: "dd/mm/yyyy hh24:mi:ss"
E) Es importante que las consultas tengan una ordenación (Ej.- "ORDER BY NLSSORT(VAL_ELE_COD, 'NLS_SORT = BINARY')"
lunes, 7 de febrero de 2011
Script - DML Paralelo (pipelined funcition + bulk DML)
Extraído de : http://www.asktherealtom.ch/?p=94
-- Tabla de ejemplo
CREATE TABLE TRANSACTION(TRANSACTION_ID NUMBER, PRUEBA VARCHAR2(100)) TABLESPACE ...;
CREATE INDEX I_PK_TRANSID ON TRANSACTION(TRANSACTION_ID) TABLESPACE ...;
-- Rellenamos la tabla
INSERT INTO TRANSACTION SELECT ... FROM ... WHERE ROWNUM <=100000;
CREATE OR REPLACE PACKAGE PKG_PARALLEL AS
TYPE t_parallel_test_row IS RECORD ( TRANSACTION_ID NUMBER(16));
TYPE t_parallel_test_ref_cursor IS REF CURSOR RETURN t_parallel_test_row;
TYPE t_dml_counter IS TABLE OF NUMBER;
TYPE t_TRANSACTIONID_tab IS TABLE OF transaction.TRANSACTION_ID%TYPE INDEX BY BINARY_INTEGER;
v_row1 t_TRANSACTIONID_tab;
v_array_size PLS_INTEGER := 500000;
function ptf_dml(p_cursor IN t_parallel_test_ref_cursor)
return t_dml_counter
pipelined
parallel_enable (PARTITION p_cursor BY ANY );
--parallel_enable (PARTITION p_cursor BY RANGE (TRANSACTIONID));
END PKG_PARALLEL;
/
SHOW ERRORS
CREATE OR REPLACE PACKAGE BODY PKG_PARALLEL AS
--create or replace function ptf_dml(p_cursor IN SYS_REFCURSOR)
function ptf_dml(p_cursor IN t_parallel_test_ref_cursor)
return t_dml_counter
pipelined
-- parallel_enable (PARTITION p_cursor BY RANGE (TRANSACTIONID))
parallel_enable (PARTITION p_cursor BY ANY )
is
PRAGMA AUTONOMOUS_TRANSACTION;
r_rowid transaction.TRANSACTION_ID%type;
BEGIN
LOOP
FETCH p_cursor BULK COLLECT INTO v_row1 LIMIT v_array_size;
FORALL i IN 1..v_row1.COUNT
UPDATE transaction t
SET t.PRUEBA = T.PRUEBA||'A'
WHERE TRANSACTION_ID=v_row1(i);
-- rollback;
commit;
pipe row (1);
EXIT WHEN p_cursor%NOTFOUND;
END LOOP;
end ptf_dml;
end PKG_PARALLEL;
/
SHOW ERRORS
alter session force parallel query parallel 4;
select count(*) from table(PKG_PARALLEL.ptf_dml( cursor(select /*+ PARALLEL(t,4) PARALLEL_INDEX(t, I_PK_TRANSID, 4) */ TRANSACTION_ID from TRANSACTION t ) ) );
-- Tabla de ejemplo
CREATE TABLE TRANSACTION(TRANSACTION_ID NUMBER, PRUEBA VARCHAR2(100)) TABLESPACE ...;
CREATE INDEX I_PK_TRANSID ON TRANSACTION(TRANSACTION_ID) TABLESPACE ...;
-- Rellenamos la tabla
INSERT INTO TRANSACTION SELECT ... FROM ... WHERE ROWNUM <=100000;
CREATE OR REPLACE PACKAGE PKG_PARALLEL AS
TYPE t_parallel_test_row IS RECORD ( TRANSACTION_ID NUMBER(16));
TYPE t_parallel_test_ref_cursor IS REF CURSOR RETURN t_parallel_test_row;
TYPE t_dml_counter IS TABLE OF NUMBER;
TYPE t_TRANSACTIONID_tab IS TABLE OF transaction.TRANSACTION_ID%TYPE INDEX BY BINARY_INTEGER;
v_row1 t_TRANSACTIONID_tab;
v_array_size PLS_INTEGER := 500000;
function ptf_dml(p_cursor IN t_parallel_test_ref_cursor)
return t_dml_counter
pipelined
parallel_enable (PARTITION p_cursor BY ANY );
--parallel_enable (PARTITION p_cursor BY RANGE (TRANSACTIONID));
END PKG_PARALLEL;
/
SHOW ERRORS
CREATE OR REPLACE PACKAGE BODY PKG_PARALLEL AS
--create or replace function ptf_dml(p_cursor IN SYS_REFCURSOR)
function ptf_dml(p_cursor IN t_parallel_test_ref_cursor)
return t_dml_counter
pipelined
-- parallel_enable (PARTITION p_cursor BY RANGE (TRANSACTIONID))
parallel_enable (PARTITION p_cursor BY ANY )
is
PRAGMA AUTONOMOUS_TRANSACTION;
r_rowid transaction.TRANSACTION_ID%type;
BEGIN
LOOP
FETCH p_cursor BULK COLLECT INTO v_row1 LIMIT v_array_size;
FORALL i IN 1..v_row1.COUNT
UPDATE transaction t
SET t.PRUEBA = T.PRUEBA||'A'
WHERE TRANSACTION_ID=v_row1(i);
-- rollback;
commit;
pipe row (1);
EXIT WHEN p_cursor%NOTFOUND;
END LOOP;
end ptf_dml;
end PKG_PARALLEL;
/
SHOW ERRORS
alter session force parallel query parallel 4;
select count(*) from table(PKG_PARALLEL.ptf_dml( cursor(select /*+ PARALLEL(t,4) PARALLEL_INDEX(t, I_PK_TRANSID, 4) */ TRANSACTION_ID from TRANSACTION t ) ) );
lunes, 17 de enero de 2011
Script - Trasponer_filas_a_columna.sql
Función plsql para transponer los resultados de una consultas (varias filas) al valor de una fila en una columna indicando un carácter separador:
create or replace FUNCTION transponer(vSQL VARCHAR2, vSEP varchar2)
RETURN VARCHAR2 IS
-- vSQL sql dinámico a lanzar cuyo resultado queremos separados por la cadena vSEP
-- vSQL debe devolver una sola columna tipo varchar2 y el total de bytes retornados no debe superar los 32000 y 4000 por registro.
TYPE cv_type IS REF CURSOR;
CV CV_TYPE;
V_RES_VALOR VARCHAR2(32000);
VALOR VARCHAR2(4000);
BEGIN
V_RES_VALOR:='XX';
OPEN CV FOR VSQL;
LOOP
FETCH CV INTO VALOR;
EXIT WHEN CV%NOTFOUND;
IF V_RES_VALOR='XX' THEN
V_RES_VALOR:=VALOR;
ELSE
V_RES_VALOR:=V_RES_VALOR||VSEP||VALOR;
END IF;
END LOOP;
CLOSE CV;
RETURN V_RES_VALOR;
EXCEPTION
WHEN OTHERS THEN
IF SQL%NOTFOUND THEN VALOR:='NO ENCONTRADO';
ELSE
VALOR:='ERROR EN LA CONSULTA, CONSULTE CON EL ADMINISTRADOR';
END IF;
IF nvl(length(V_RES_VALOR),0)=0 THEN
V_RES_VALOR:=VALOR;
ELSE
V_RES_VALOR:=V_RES_VALOR||' '||VSEP||' '||VALOR;
END IF;
RETURN 'ERROR --> '||V_RES_VALOR;
END TRANSPONER;
/
Ejemplo de uso:
select transponer('SELECT table_name FROM user_tables WHERE ROWNUM <=100', '|') FROM DUAL;
TABLA1|TABLA2|TABLA_EJEMPLO|PRUEBA
create or replace FUNCTION transponer(vSQL VARCHAR2, vSEP varchar2)
RETURN VARCHAR2 IS
-- vSQL sql dinámico a lanzar cuyo resultado queremos separados por la cadena vSEP
-- vSQL debe devolver una sola columna tipo varchar2 y el total de bytes retornados no debe superar los 32000 y 4000 por registro.
TYPE cv_type IS REF CURSOR;
CV CV_TYPE;
V_RES_VALOR VARCHAR2(32000);
VALOR VARCHAR2(4000);
BEGIN
V_RES_VALOR:='XX';
OPEN CV FOR VSQL;
LOOP
FETCH CV INTO VALOR;
EXIT WHEN CV%NOTFOUND;
IF V_RES_VALOR='XX' THEN
V_RES_VALOR:=VALOR;
ELSE
V_RES_VALOR:=V_RES_VALOR||VSEP||VALOR;
END IF;
END LOOP;
CLOSE CV;
RETURN V_RES_VALOR;
EXCEPTION
WHEN OTHERS THEN
IF SQL%NOTFOUND THEN VALOR:='NO ENCONTRADO';
ELSE
VALOR:='ERROR EN LA CONSULTA, CONSULTE CON EL ADMINISTRADOR';
END IF;
IF nvl(length(V_RES_VALOR),0)=0 THEN
V_RES_VALOR:=VALOR;
ELSE
V_RES_VALOR:=V_RES_VALOR||' '||VSEP||' '||VALOR;
END IF;
RETURN 'ERROR --> '||V_RES_VALOR;
END TRANSPONER;
/
Ejemplo de uso:
select transponer('SELECT table_name FROM user_tables WHERE ROWNUM <=100', '|') FROM DUAL;
TABLA1|TABLA2|TABLA_EJEMPLO|PRUEBA
Script - Snaps AWR con más accesos a disco
Detectamos el snap_id con mayor número de lecturas y escrituras físicas de las estadísticas AWR almacenadas.
select
b.snap_id, sum(b.ios-a.ios)
from
(select snap_id, file#, phyrds+phywrts ios
from
dba_hist_filestatxs dhf) a,
(select snap_id, file#, phyrds+phywrts ios
from
dba_hist_filestatxs dhf) b
where
a.snap_id+1=b.snap_id and
a.file#=b.file#
group by a.snap_id order by 2
select * from dba_hist_snapshot where snap_id=....
select
b.snap_id, sum(b.ios-a.ios)
from
(select snap_id, file#, phyrds+phywrts ios
from
dba_hist_filestatxs dhf) a,
(select snap_id, file#, phyrds+phywrts ios
from
dba_hist_filestatxs dhf) b
where
a.snap_id+1=b.snap_id and
a.file#=b.file#
group by a.snap_id order by 2
select * from dba_hist_snapshot where snap_id=....
viernes, 7 de enero de 2011
Comando - Table_lock
alter table '||owner||'.'||table_name||' disable table lock;
Con este comando evitamos un nivel de enqueues o bloqueos en el motor oracle, los tipo TM, permitiendo agilizar estos procesos de gestión de bloqueos, las estadísticas del AWR que se mejoran son:
enqueue releases
enqueue requests
las cuales bajan muchísimo.
Con esta opción en tablas críticas OLTP, bajamos los requerimientos de CPU en sistemas cargados entre un 5-10%.
Hay que tener en cuenta que desabilitar el "table_lock" sobre una tabla implica no poder realizar operaciones DDL sobre ellas (truncate, alter ...) así hay que tenerlo en cuenta para sistemas que requieran este tipo de bloqueos, aunque también es una medida extra de seguridad.
Con este comando evitamos un nivel de enqueues o bloqueos en el motor oracle, los tipo TM, permitiendo agilizar estos procesos de gestión de bloqueos, las estadísticas del AWR que se mejoran son:
enqueue releases
enqueue requests
las cuales bajan muchísimo.
Con esta opción en tablas críticas OLTP, bajamos los requerimientos de CPU en sistemas cargados entre un 5-10%.
Hay que tener en cuenta que desabilitar el "table_lock" sobre una tabla implica no poder realizar operaciones DDL sobre ellas (truncate, alter ...) así hay que tenerlo en cuenta para sistemas que requieran este tipo de bloqueos, aunque también es una medida extra de seguridad.
Suscribirse a:
Entradas (Atom)