Technological recipes that I've held to prepare some solutions DBA environment. (by Felipe Donoso Bastias)

14 Jul 2019

Algunas conceptos de SQL_ID, HASH_VALUE, etc..


Una aclaración corta pero necesaria del SQL_ID.

Oracle cuando realiza parsing de una consulta, genera con un algoritmo un Hashing MD5 de 128 bits de largo para cada consulta. Luego toma los últimos 64 bits de dicho hashing y crea lo que conocemos hoy en día como SQL_ID, el cual tiene 13 caracteres de largo. Este se compone de una mezcla de números y letras (base32), es decir 32 caracteres en total que serán usados para dar forma al hashing de SQL_ID final (de 13 caracteres).

Por ejemplo si ejecutamos una simple consulta como: select * from dual ; veremos que en el interior de la shared_pool se creará un nuevo SQL_ID, seguido de un hash_value. Ejemplo:


SQL> select * from dual;

D
-
X

SQL> 
SQL> select sql_id, hash_value from v$sql
where sql_text = 'select * from dual';  2  

SQL_ID       HASH_VALUE
------------- ----------
a5ks9fhw2v9s1  942515969



Lo anterior entrega el SQL_ID: a5ks9fhw2v9s1 y a partir de dicho SQL_ID oracle también crea el valor del identificador HASH_VALUE. Este valor era el que se usaba para identificar a una consulta en las versiones oracle 9i hacia atrás. Hay una diferencia eso si que cabe recalcar, en oracle9i y en oracle10g el algoritmo que se ocupa para crear ese hash_value es distinto. La vista GV$SQL o V$SQL posee la columna old_hash_value para mostrar también el valor hash_value que tendría nuestro SQL_ID pero como si fuese visto sobre un motor oracle9i o anterior.

A modo de ejemplo oracle crea el hash_value de la consulta ocupando el siguiente algoritmo (ocupando como parámetro el SQL_ID):

(la consulta original está en la página del genial TanelPoder, abajo en la bibliografia se encuentra el link original)

select
trunc(mod(sum((instr('0123456789abcdfghjkmnpqrstuvwxyz',substr(lower(trim('a5ks9fhw2v9s1')),level,1))-1)
                       *power(32,length(trim('a5ks9fhw2v9s1'))-level)),power(2,32))) hash_value
from
    dual
connect by
    level <= length(trim('a5ks9fhw2v9s1'))

Si ejecutamos la consulta usando el sql_id del ejemplo anterior para la query "select * from dual", veremos que entrega el mismo hash_value visto en la consulta anterior:

HASH_VALUE
----------
 942515969


Como mencionamos anteriormente el sql_id es una mezcla de hashing md5 y funciones Hexadecimales con 32 caracteres que retorna un número de 13 dígitos de largo. El algoritmo usado para generar lo anterior que mencionamos que da forma al SQL_ID, puede ser visto con la siguiente función que ha creado el señor Carlos Sierra (al final se encuentra el link hacia la fuente original)

CREATE OR REPLACE FUNCTION compute_sql_id (sql_text IN CLOB)
RETURN VARCHAR2 IS
 BASE_32 CONSTANT VARCHAR2(32) := '0123456789abcdfghjkmnpqrstuvwxyz';
 l_raw_128 RAW(128);
 l_hex_32 VARCHAR2(32);
 l_low_16 VARCHAR(16);
 l_q3 VARCHAR2(8);
 l_q4 VARCHAR2(8);
 l_low_16_m VARCHAR(16);
 l_number NUMBER;
 l_idx INTEGER;
 l_sql_id VARCHAR2(13);
BEGIN
 l_raw_128 := /* use md5 algorithm on sql_text and produce 128 bit hash */
 SYS.DBMS_CRYPTO.hash(TRIM(CHR(0) FROM sql_text)||CHR(0), SYS.DBMS_CRYPTO.hash_md5);
 l_hex_32 := RAWTOHEX(l_raw_128); /* 32 hex characters */
 l_low_16 := SUBSTR(l_hex_32, 17, 16); /* we only need lower 16 */
 l_q3 := SUBSTR(l_low_16, 1, 8); /* 3rd quarter (8 hex characters) */
 l_q4 := SUBSTR(l_low_16, 9, 8); /* 4th quarter (8 hex characters) */
 /* need to reverse order of each of the 4 pairs of hex characters */
 l_q3 := SUBSTR(l_q3, 7, 2)||SUBSTR(l_q3, 5, 2)||SUBSTR(l_q3, 3, 2)||SUBSTR(l_q3, 1, 2);
 l_q4 := SUBSTR(l_q4, 7, 2)||SUBSTR(l_q4, 5, 2)||SUBSTR(l_q4, 3, 2)||SUBSTR(l_q4, 1, 2);
 /* assembly back lower 16 after reversing order on each quarter */
 l_low_16_m := l_q3||l_q4;
 /* convert to number */
 SELECT TO_NUMBER(l_low_16_m, 'xxxxxxxxxxxxxxxx') INTO l_number FROM DUAL;
 /* 13 pieces base-32 (5 bits each) make 65 bits. we do have 64 bits */
 FOR i IN 1 .. 13
 LOOP
 l_idx := TRUNC(l_number / POWER(32, (13 - i))); /* index on BASE_32 */
 l_sql_id := l_sql_id||SUBSTR(BASE_32, (l_idx + 1), 1); /* stitch 13 characters */
 l_number := l_number - (l_idx * POWER(32, (13 - i))); /* for next piece */
 END LOOP;
 RETURN l_sql_id;
END compute_sql_id;
/

Si creamos esa función en nuestra BD y la ejecutamos indicando nuestro Statement completo como parámetro veremos el mismo SQL_ID que habíamos visto en la shared pool al comienzo:
SQL> SELECT compute_sql_id('select * from dual') sql_id from dual ;

SQL_ID
--------------------------------------------------------------------------------

a5ks9fhw2v9s1


Ahora surge una pregunta que muchas personas pueden hacerse ¿Puede repetirse un SQL_ID para dos consultas absolutamente distintas? La respuesta es SI. Ya en el hash_value las colisiones se sabia que podían existir (y eso que el algoritmo trabaja en ese caso con un Hashing de 32bits). Para evitar eso se creo el SQL_ID basado en un algoritmo que genera un número único mucho más largo. En algunas pruebas realizadas por un DBA del Cern llamado Luca Canali (a quien recomiendo leer mucho para eso ver link de su nota al respecto en la bibliografía) se encontró que se necesitaron generar casi 10billones de pruebas con consultas de texto similares para generar algunas pocas colisiones. Eso demuestra que actualmente el SQL_ID es la manera más eficiente de asegurar la identificación única para una consulta en la base de datos.

En resumen el SQL_ID es fruto de funciones Hexadecimales y conversiones MD5 que resulta en un número de 13 digitos, y el hash_value es formado por los últimos 32bits del hashing md5 del SQL_ID.

Aquí la bibliografía que recomiendo leer Bibliografía:
https://blog.tanelpoder.com/2009/02/22/sql_id-is-just-a-fancy-representation-of-hash-value/
Share:

27 Jun 2019

Agregar nueva tabla a un ambiente de Replicación Golden Gate Existente



Esto es el paso a paso para agregar una nueva tabla a un ambiente de replicación de Golden Gate ya existente. En este caso agregaremos dos nuevas tablas sobre un extractor, pump y replicador de Golden Gate.

Tablas a agregar:
SIEBEL.CX_ELEGIBILIDAD
SIEBEL.CX_ITEM_ELEGI

Extractores, Pump y Replicadores que editaremos:
Extractor: E_S_STG1    
PMP:   P_S_STG1    
Replicador: R_S_STG1    

1.    Primer paso es detener el replicador en el cual agregaremos nuestra tabla en el ambiente de DESTINO o TARGET:

[oracle@miscanti oragg]$ ./ggsci

Oracle GoldenGate Command Interpreter for Oracle
Version 12.1.2.1.0 OGGCORE_12.1.2.1.0_PLATFORMS_140727.2135.1_FBO
Linux, x64, 64bit (optimized), Oracle 12c on Aug 7 2014 10:21:34
Operating system character set identified as UTF-8.

Copyright (C) 1995, 2014, Oracle and/or its affiliates. All rights reserved.



GGSCI (miscanti) 1> info all

Program     Status Group       Lag at Chkpt Time Since Chkpt

MANAGER     RUNNING
REPLICAT    RUNNING R_B_STG1    00:00:40 00:00:07
REPLICAT    RUNNING R_S_STG1    00:00:00 00:00:04


GGSCI (miscanti) 2> stop R_S_STG1

Sending STOP request to REPLICAT R_S_STG1 ...
Request processed.


GGSCI (miscanti) 4> info all

Program     Status Group       Lag at Chkpt Time Since Chkpt

MANAGER     RUNNING
REPLICAT    RUNNING R_B_STG1    00:00:00 00:00:07
REPLICAT    STOPPED     R_S_STG1    00:00:00      00:04:12


Tenemos que asegurarnos de que el replicador no vuelva a subir de nuevo.

2.    Ahora en el ambiente de ORIGEN procederemos activar el supplemental logging de las tablas (usando la herramienta de ggsci y conectados a la instancia de BD):

GGSCI (edc01dbadm03.vtr.cl) 1> info all

Program     Status Group       Lag at Chkpt Time Since Chkpt

MANAGER     RUNNING
EXTRACT     RUNNING     E_S_STG1    00:00:04      00:00:09
EXTRACT     RUNNING P_S_STG1   00:00:00 00:00:06

GGSCI (edc01dbadm03.vtr.cl) 2> DBLOGIN USERID ogg_user@SBLQA, PASSWORD oracle
Successfully logged into database.

GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 3> ADD TRANDATA SIEBEL.CX_ELEGIBILIDAD

Logging of supplemental redo data enabled for table SIEBEL.CX_ELEGIBILIDAD.
TRANDATA for scheduling columns has been added on table 'SIEBEL.CX_ELEGIBILIDAD'.
GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 4>

GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 4> ADD TRANDATA SIEBEL.CX_ITEM_ELEGI

Logging of supplemental redo data enabled for table SIEBEL.CX_ITEM_ELEGI.
TRANDATA for scheduling columns has been added on table 'SIEBEL.CX_ITEM_ELEGI'.


3.    Agregamos las tablas a los archivos de parámetros de extractor y pump (E_S_STG1 y P_S_STG1)

(agregamos la tabla al Extractor)
GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 5> edit param E_S_STG1
(agregamos las siguientes tablas al final del archivo de parámetros y guardamos:)
TABLE SIEBEL.CX_ELEGIBILIDAD;
TABLE SIEBEL.CX_ITEM_ELEGI;


(agregamos la tabla al PUMP)
GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 6> edit param P_S_STG1
(agregamos las siguientes tablas al final del archivo de parámetros y guardamos:)
TABLE SIEBEL.CX_ELEGIBILIDAD;
TABLE SIEBEL.CX_ITEM_ELEGI;



4.    Posterior detenemos el extractor y el pump:
GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 11> stop P_S_STG1

Sending STOP request to EXTRACT P_S_STG1 ...
Request processed.


GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 12> stop E_S_STG1

Sending STOP request to EXTRACT E_S_STG1 ...
Request processed.


GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 13> info all

Program     Status Group       Lag at Chkpt Time Since Chkpt

MANAGER     RUNNING
EXTRACT     STOPPED     E_S_STG1    00:00:05      00:00:03
EXTRACT     STOPPED P_S_STG1    00:00:00 00:00:17



5.    Posteriormente levantamos el PUMP y luego el Extractor nuevamente (EN ESE ORDEN)

GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 15> start P_S_STG1

Sending START request to MANAGER ...
EXTRACT P_S_STG1 starting


GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 16> start E_S_STG1

Sending START request to MANAGER ...
EXTRACT E_S_STG1 starting

GGSCI (edc01dbadm03.vtr.cl as ogg_user@SBLQA4) 18> info all

Program     Status Group       Lag at Chkpt Time Since Chkpt

MANAGER     RUNNING
EXTRACT     RUNNING     E_S_STG1    00:00:04      00:00:04
EXTRACT     RUNNING P_S_STG1    00:00:00 00:00:02


6.    Procederemos ahora desde sqlplus a obtener el SCN actual de la base de datos de ORIGEN. Este valor será importante y lo usaremos para sacar un expdp de las tablas:

[oracle@edc01dbadm03 expdp_gg]$ sqlplus "/as sysdba"

SQL*Plus: Release 12.1.0.2.0 Production on Thu Jun 27 18:24:53 2019

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


Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Advanced Analytics and Real Application Testing options

SQL>  select to_char(dbms_flashback.get_system_change_number()) from dual;

TO_CHAR(DBMS_FLASHBACK.GET_SYSTEM_CHANGE
----------------------------------------
14977510302280

SQL> exit
Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Advanced Analytics and Real Application Testing options


7.    Con el valor anterior (14977510302280) procederemos a exportar las tablas (con exp o expdp)

 [oracle@edc01dbadm03 expdp_gg]$ exp userid=ogg_user/oracle@SBLQA CONSISTENT=y flashback_scn=14977510302280 file=exp01.dmp log=exp01.log TABLES=SIEBEL.CX_ELEGIBILIDAD,SIEBEL.CX_ITEM_ELEGI

Export: Release 12.1.0.2.0 - Production on Thu Jun 27 18:25:28 2019

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


Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Advanced Analytics and Real Applicat
Export done in AL32UTF8 character set and AL16UTF16 NCHAR character set

About to export specified tables via Conventional Path ...
Current user changed to SIEBEL
. . exporting table                CX_ELEGIBILIDAD 286 rows exported
. . exporting table                  CX_ITEM_ELEGI 5930 rows exported
Export terminated successfully without warnings.

8.    Una vez terminada la exportación nos llevaremos el archivo DMP exp01.dmp al servidor de DESTINO donde tenemos nuestro replicador:
[oracle@edc01dbadm03 expdp_gg]$ scp /goldeng/expdp_gg/exp01.dmp USR_GOLDENG@miscanti.vtr.cl:/u01/app/expdp_gg
USR_GOLDENG@miscanti.vtr.cl's password:
exp01.dmp                                                                                                   100% 1264KB 1.2MB/s 00:00
[oracle@edc01dbadm03 expdp_gg]$

9.    En el servidor de DESTINO revisamos que el archivo se encuentre ok:
[oracle@miscanti oragg]$ cd /u01/app/expdp_gg
[oracle@miscanti expdp_gg]$ ls -lptr
total 6058504
-rw-r--r--. 1 USR_GOLDENG USR_GOLDENG    1294336 Jun 27 19:35 exp01.dmp

10.  En este  server de DESTINO procederemos a importar las tablas nuevas:

[oracle@miscanti expdp_gg]$ imp userid=ogg_user/oracle@STAGING1 file=exp01.dmp log=exp_imp01.log FROMUSER=SIEBEL TOUSER=SIEBEL TABLES=CX_ELEGIBILIDAD,CX_ITEM_ELEGI

Import: Release 12.2.0.1.0 - Production on Thu Jun 27 19:38:37 2019

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


Connected to: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

Export file created by EXPORT:V12.01.00 via conventional path
import done in AL32UTF8 character set and AL16UTF16 NCHAR character set

. importing SIEBEL's objects into SIEBEL
. . importing table              "CX_ELEGIBILIDAD" 286rows imported
. . importing table                "CX_ITEM_ELEGI" 5930rows imported
Import terminated successfully with warnings.

11.  Ya terminado el import de las tablas, ingresamos a la herramienta de GGSCI sobre este ambiente de DESTINO y procederemos a agregar las nuevas tablas al archivo de parámetros del replicador. Pero en este caso usaremos la keyword FILTER en el archivo de parámetros, para indicar a partir de que SCN se pueden comenzar a aplicar los cambios para las nuevas tablas que vengan en los trails files. Este SCN es el mismo con el cual realizamos el export anterior desde el ORIGEN:


GGSCI (miscanti) 2> edit param R_S_STG1


--Agregamos lo siguiente al final del archivo de param.
--teniendo precaución con el valor que 
--estamos usando para el atributo CSN
MAP  SIEBEL.CX_ELEGIBILIDAD,   TARGET SIEBEL.CX_ELEGIBILIDAD ,FILTER ( @GETENV ('TRANSACTION', 'CSN') > 14977510302280);
MAP  SIEBEL.CX_ITEM_ELEGI,     TARGET SIEBEL.CX_ITEM_ELEGI   ,FILTER ( @GETENV ('TRANSACTION', 'CSN') > 14977510302280); 

12.  Subimos posteriormente el replicador en este ambiente de DESTINO:
GGSCI (miscanti) 4> start R_S_STG1

Sending START request to MANAGER ...
REPLICAT R_S_STG1 starting

GGSCI (miscanti) 6> info all

Program     Status Group       Lag at Chkpt Time Since Chkpt

MANAGER     RUNNING
REPLICAT    RUNNING R_B_STG1    00:00:52 00:00:01
REPLICAT    RUNNING     R_S_STG1 00:00:00      00:00:05

Eso es todo, ya con el replicador corriendo ya se pueden eliminar los comandos FILTER del archivo de parámetros del replicador.

Espero sea de utilidad, 
Saludos, Felipe.

Share:

Copyright © DBA TIPS | Powered by Blogger
Design by SimpleWpThemes | Blogger Theme by NewBloggerThemes.com | Free Blogger Templates