I stand corrected… TTUs for Apple OS X

8 mayo \08\UTC 2015

En alguna entrada de este blog dije que no existían TTUs para Mac. Pues bien: estaba equivocado. Las TTUs para Mac (una versión reducida de las TTUs, en realidad) existen, aunque no son de ‘dominio público’. Se deben bajar de Teradata At Your Service.

Si puedes conseguirlas, están en forma de .tar.gz:

TeradataToolsAndUtilitiesBase__macosx_x86_64.15.10.01.00.tar.gz

No hay mas que descomprimirlas a un directorio de trabajo (donde se descomprimirán en forma de directorio “Teradata_Client“) y allí está el TeradataToolsAndUtilities15.10.01.00.pkg. Pinchas en él y aparece el instalador, en el que pinchas ‘continue’, ‘continue’, ‘continue’… ‘install’ y:

TTUs On Mac 1

TTUs On Mac 1

 

La instalación queda ubicada en /Applications/Teradata Client 15.10/ y el software en /Library/Application Support/teradata/client/15.10/

TTUs On Mac 2

TTUs On Mac 2

Saludos.

Carlos.


Arreglando Teradata Studio en Teradata Express for VMware

23 abril \23\UTC 2015

Hace algún tiempo decidí instalar Teradata Studio 15 en la máquina virtual de Teradata 14.10 sobre SLES11. Bajé el fichero comprimido desde downloads.teradata.com y seguí las instrucciones (descomprimir el tar.gz, ejecutar como ‘root‘ studioinstall, etc…) y Teradata Studio 15 quedó instalado.

Pero las cosas se empezaron a torcer cuando comencé a utilizarlo: cada vez que abría una ‘perspectiva’ de ‘query development‘ la aplicación se cerraba. Miré los logs y allí se indicaba que había un problema:

Problematic frame: libpangoft2-1.0.so.0+0x18df1

Miré y miré, le pregunté a Francine Grimmer, quien me dijo que borrase el ‘workspace’ y empezase otra vez, pero no obtuve ningún cambio visible. Así que dejé el tema aparcado…

Recientemente apareció Teradata Studio 15.10, y pensé “¡Ya está! Desinstalo la versión 15.0, instalo la 15.10 y seguramente los problemas desaparecerán…” Qué iluso.

Después de desinstalar la 15.0, bajarme e instalar la 15.10 el problema seguía exactamente igual. Así que, cabezón que es uno, me puse a investigar cuál podría ser el problema. Después de mucho buscar, encontré una referencia a un problema del java runtime environment (jre) 1.6 que viene instalado en la máquina virtual de Teradata 14.10 sobre SLES11. Solución: actualizarlo.

Así pues, me bajé la última versión (jre1.8) desde el ‘site’ de Oracle (puajjj) y me dispuse a instalarla en forma de rpm (rpm -ivh …) Pero aquí también pinché en hueso: la instalación abortaba reclamando ‘alternatives’. Esto lo solucioné con un symbolyc link de ‘update-alternatives’ mediante:

ln -s /usr/sbin/update-alternatives /usr/sbin/alternatives

y ejecutando la instalación del jre con:

rpm -ivh --nodeps jre-8u45-linux-x64.rpm

So far, so good, pero ahora hay que indicarle al sistema que utilice este jre 1.8 en vez del corrupto 1.6. Esto lo hacemos editando el fichero /etc/profile (que todos los usuarios cargarán por defecto). Allí sustituimos:

PATH=/opt/teradata/jvm64/jre6/jre/bin:"${PATH}"; export PATH

por:

PATH=/usr/java/jre1.8.0_45/bin:"${PATH}"; export PATH

Y con estos cambios, probamos a ver si hemos arreglado el problema de la ‘query development perspective‘:

Teradata Studio 15.10Teradata Studio 15.10

Teradata Studio 15.10

¡OK!

Saludos.

Carlos.


SQL a Teradata desde Oracle (II): Oracle Database Gateways

21 abril \21\UTC 2015

Aprovechando que tenemos instalado en el servidor CentOS 6 el driver ODBC de Teradata y como allí hay instalado un Oracle 11g, vamos a retomar el viejo tema de la conexión de Oracle a Teradata. Anteriormente (Oracle 10g) esto se hacía mediante “Heterogeneous Services”. Más recientemente esto se hace mediante los llamados “Oracle Database Gateways”, y en nuestro caso particular con el “Oracle Database Gateway for ODBC”, heredero directo de aquellos “Heterogeneous Services” que configuramos en su día en un servidor Windows.

Los pasos son fundamentalmente los mismos, aunque con las particularidades propias del Sistema Operativo (de Windows a CentOS). También cambian algunos pequeños detalles, como los nombres de los módulos (ya no se llama “hsodbc”, sino que ahora su nombre es “dg4odbc”).

Así pues, vamos por partes.

Si queremos que la configuración ODBC sea global y no sólo para un usuario (quién sabe quién arrancará Oracle) deberemos especificarlo en el entorno (esto es análogo a la definición de DSN “de sistema” en Windows). En nuestro caso hemos creado el fichero /opt/odbc/.odbc.ini con los datos del DSN ODBC de Teradata (TD1410_SLES11, los mismos que utilizamos aquí). Definimos para ello una variable de entorno “ODBCINI” que apunte a él.

Con esto (y tras haberlo probado, con tdxodbc como también dijimos aquí) podemos comenzar.

Primero hay que crear un fichero de parámetros de inicialización para el “Gateway ODBC”. Se crea en $ORACLE_HOME/hs/admin y su nombre debe ser init<SID>.ora, siendo SID el identificador de sistema para el sitio remoto. En nuestro caso el fichero se llamará initTD1410.ora y, entre otros, contendrá los parámetros:

HS_FDS_CONNECT_INFO = TD1410_SLES11
HS_FDS_SHAREABLE_NAME = /usr/lib64/libodbc.so

En realidad /usr/lib64/libodbc.so es un symbolic link al “driver manager” odbc de Teradata que instalamos en su día en /opt/teradata/client/ODBC_64/lib/libodbc.so

Una vez con nuestro initTD1410.ora, vamos a configurar el listener para el “Gateway”, para ello añadiremos una entrada en listener.ora:

...
  (SID_DESC= 
     (SID_NAME = TD1410)
     (ORACLE_HOME = <valor de $ORACLE_HOME>)
     (PROGRAM = dg4odbc)
     (ENVS = "LD_LIBRARY_PATH=/usr/lib64:<valor de $ORACLE_HOME>/lib")
  )

Tras hacer estas modificaciones debemos parar (lsnrctl stop) y volver a arrancar (lsnrctl start) el listener y ver que su estado (lsnrctl status) es correcto.

[carlos@CentOS6 ~]$ lsnrctl status

LSNRCTL for Linux: Version 11.2.0.2.0 - Production
...
Service "TD1410" has 1 instance(s).
  Instance "TD1410", status UNKNOWN, has 1 handler(s) for this service...
  ...

Ahora hay que hacer que Oracle pueda comunicarse con el “Gateway”. Y esto lo hacemos mediante el nunca bien conocido y siempre temido tnsnames.ora (¡Uuuuhhhh!, ¡tnsnames, qué miedo!). Pero no es para tanto. Sólo hay que incluir el “connect descriptor” y ya está:

teradata.remote =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = CentOS6.2_64)(PORT = 1521))
    (CONNECT_DATA = (SID = TD1410))
    (HS=OK)
  )

Es muy importante no olvidarse del (HS=OK) ni de hacerse un lío con tanto paréntesis abierto y cerrado.

Podemos comprobar que todo va bien con tnsping:

[carlos@CentOS6 ~]$ tnsping teradata.remote

TNS Ping Utility for Linux: Version 11.2.0.2.0 - Production on 21-APR-2015 19:58:59

Copyright (c) 1997, 2011, Oracle.  All rights reserved.

Used parameter files:


Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = CentOS6.2_64)(PORT = 1521)) (CONNECT_DATA = (SID = TD1410)) (HS=OK))
OK (0 msec)
[carlos@CentOS6 ~]$ 

Bueno, pues ya casi está. Sólo queda crear el dblink :

CARLOS@CentOS6.2_64> CREATE DATABASE LINK teradata.remote 
  2  CONNECT TO carlos IDENTIFIED BY xxxxxxxx 
  3  USING 'teradata.remote';

Database link created.

Y ver que efectivamente podemos seleccionar datos de Teradata desde Oracle:

CARLOS@CentOS6.2_64> select * 
  2  from carlos.prueba01@teradata.remote;

      ID_N D_DATE
---------- -------------------
         3 2014/09/18 00:00:00
         1 2014/09/18 00:00:00
         2 2014/09/18 00:00:00

Mission accomplished!

Saludos.

Carlos.


No siempre es lo mismo…

25 marzo \25\UTC 2015

La conversión de tipos explícita (casting) en Teradata puede hacerse de dos modos: el “nativo”, que consiste en añadir entre paréntesis el tipo destino junto al valor al que queremos transformar; y el ANSI, mediante la construcción CAST(… AS …).

Ambas formas son correctas y casi siempre intercambiables, pero hay excepciones:

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT 123456 (CHAR(6)),
       CAST(123456 AS CHAR(6));


 *** Query completed. One row found. 2 columns returned.
 *** Total elapsed time was 1 second.

123456  123456
------  ------
     1  123456

 BTEQ -- Enter your SQL request or BTEQ command:

En efecto, el modo nativo efectúa una conversión automática a partir del valor original (un integer, de rango -2147483648 , 2147483647), que necesita 11 posiciones. Al convertirlo a CHAR(6) toma los primeros 5 espacios y trunca desde ahí (por eso solamente muestra ‘1’), mientras que el ANSI elimina (trim) los espacios de inicio al crear la cadena final.

Saludos.

Carlos.


Instalando el Teradata ODBC driver en Linux 64 (CentOS 6)

6 marzo \06\UTC 2015

Por motivos que no vienen al caso, pero que están en cierto modo relacionados con esto, tuve que instalar el Teradata ODBC driver para Linux 64 en un CentOS 6.

Viendo la documentación, me pareció que había aspectos de la instalación que no estaban demasiado claros, cosa que pude comprobar después de consultar un poco la web. No obstante, como valiente que es uno, eso no me apartó del objetivo.

Lo primero, descargar el driver en http://downloads.teradata.com/download/connectivity/odbc-driver/linux

Es un “.tar.gz” que contiene los .rpm de tdicu (Teradata International Components for Unicode), tdgss (Teradata Generic Security Services) y tdodbc (el driver en sí).

Tras instalar tdicu, tdgss y tdodbc (rpm -ivh) es cuando vienen los puntos peliagudos:

Hay que copiar odbc.ini de /opt/teradata/client/15.00/odbc_64 a $HOME/.odbc.ini . Nótese que el fichero en $HOME debe ser ‘oculto’ comenzando con un punto: .odbc.ini

Una vez hecho esto, hay que editarlo para incluir el origen ODBC al cual queremos acceder (en nuestro caso, un Teradata 14.10 sobre SLES 11) agregando las entradas necesarias:

 

[ODBC Data Sources]
TD1410_SLES11=tdata.so
...

[TD1410_SLES11]
Driver=/opt/teradata/client/ODBC_64/lib/tdata.so
Description=Teradata 14.10 on SLES 11
DBCName=TD1410
...

Pero ahí no acaba todo, ya que nos quedan por fijar un par de variables de entorno sin las cuales la cosa no funciona.

Hay que fijar variables de entorno en .bash_profile:

#Teradata ODBC:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/teradata/client/15.00/odbc_64/lib
export LD_LIBRARY_PATH

NLSPATH=/opt/teradata/client/15.00/odbc_64/msg/%N.cat
export NLSPATH

Porque la instalación fija variables de entorno en /etc/profile y en /etc/csh.login y éstas apuntan al entorno erróneo. Es por eso que suelen aparecer los errores “Specified driver could not be loaded” y “Unable to get catalog string“.

Una vez hecho todo esto, sólo hay que probar:

[carlos@centos-6 bin]$ ./tdxodbc 

Enter Data Source Name: TD1410_SLES11
Enter UserID: carlos
Enter Password: 

Connecting with SQLConnect(DSN=TD1410_SLES11,UID=carlos,PWD=*)...

.....ODBC connection successful.

ODBC version        = -03.52.0000-
DBMS name           = -Teradata-
DBMS version        = -14.10.0002  14.10.00.02-
Driver name         = -tdata.so-
Driver version      = -15.00.00.03-
Driver ODBC version = -03.51-

(type quit to terminate adhoc) 
Enter SQL string : SELECT DATE;

Executing SQLExecDirect("SELECT DATE;")...

SQL Statement [1]: 1 rows affected.

Date 
2015-03-05 

Enter SQL string : quit

'quit' command detected

ODBC connection closed.
[carlos@centos-6 bin]$ 

Y… ¡éxito!

Saludos.

Carlos.


DIRTY READS

13 febrero \13\UTC 2015

 

Teradata funciona en ISOLATION LEVEL SERIALIZABLE por defecto. Esto significa que para garantizar la integridad de los datos se implementan bloqueos que impiden modificaciones de los mismos por otras transacciones mientras estos están siendo leídos. Esta política de bloqueos es bastante restrictiva en sí (READERS BLOCK WRITERS) aunque es la más segura a la hora de garantizar integridad. Hay que tener en cuenta que en Datawarehouses lo normal es leer mucho y modificar poco (READERS DON’T BLOCK READERS). Otras bases de datos más orientadas a OLTP funcionan de otras formas (READ COMMITED en Oracle, por ejemplo. READERS DON’T BLOCK WRITERS)

Teradata nos permite relajar los bloqueos de lectura de forma que no interfiramos la actividad de actualización de tablas sobre las que únicamente queremos leer para que otras transacciones puedan desarrollar dichas actividades de actualización. La forma más habitual de hacerlo es con el modificador LOCKING … FOR ACCESS. Con este modificador podremos leer los datos sin bloquearlos, permitiendo actividades de actualización por parte de otras transacciones. Pero a un coste: estaremos permitiendo los llamados ‘dirty reads’: lectura de datos modificados por otras transacciones pero sobre los que no se ha hecho COMMIT (ISOLATION LEVEL READ UNCOMMITED). Esto puede tener consecuencias no deseadas.

Lo podemos ver con un ejemplo ‘de la vida real’. Uso la siguiente ‘query‘ para monitorizar la actividad sobre una tabla por parte de un agente externo que realiza constantes borrados e inserciones sobre ella:

 BTEQ -- Enter your SQL request or BTEQ command:
LOCKING TABLE THE_DATABASE.THE_TABLE FOR ACCESS
SELECT CURRENT_TIMESTAMP (FORMAT 'YYYY-MM-DDbhh:mi:ss') FECHA,
       ZEROIFNULL(SUM (CASE WHEN TS_PROCESADO IS NULL 
                            THEN 1 ELSE 0 END)) PENDIENTES,
       ZEROIFNULL(SUM (CASE WHEN TS_PROCESADO IS NOT NULL 
                            THEN 1 ELSE 0 END)) PROCESADOS,
       PENDIENTES + PROCESADOS TOTAL,
       MAX(TS_TIMESTAMP) ULTIMO_INSERTADO
  FROM THE_DATABASE.THE_TABLE
;


 *** Query completed. One row found. 6 columns returned.
 *** Total elapsed time was 1 second.

              FECHA PENDIENTES PROCESADOS TOTAL    ULTIMO_INSERTADO
------------------- ---------- ---------- ----- -------------------
2015-02-11 09:36:00          5         15    20 2015-02-11 09:36:00

 BTEQ -- Enter your SQL request or BTEQ command:
=1


 *** Query completed. One row found. 6 columns returned.
 *** Total elapsed time was 1 second.

              FECHA PENDIENTES PROCESADOS TOTAL    ULTIMO_INSERTADO
------------------- ---------- ---------- ----- -------------------
2015-02-11 09:36:02          0         20    20 2015-02-10 12:32:17

Aquí se ve como en la primera ejecución de la query estábamos leyendo datos modificados por una transacción del agente (había borrado cinco filas y las había vuelto a insertar como ‘pendientes’) pero sobre los que aun aun no había efectuado un COMMIT. Por algún problema en la transacción -o por una orden explícita- ésta es abortada con el consiguiente ROLLBACK, de tal forma que las segunda ejecución de nuestra SELECT (apenas dos segundos después) muestra los datos tal y como estaban al comienzo de la transacción abortada.

Hay que hacer notar que, al no existir un COMMIT, hemos leído datos que nunca han existido “realmente” en la base de datos.

Como siempre: no se trata de que esto sea algo malo o bueno, se trata de saber las necesidades y asumir los posibles efectos de aplicar las diferentes técnicas.

Nota: mis compañeros A. y N. lo vieron ‘in situ‘ y me animaron a escribir esto.

Saludos.

Carlos.


Teradata Unity implementation workshop

10 enero \10\UTC 2015

Esta semana la he pasado haciendo el Teradata Unity implementation workshop. Un ‘hands on workshop‘ que te da la oportunidad de conocer, utilizar y experimentar con los diferentes productos del ecosystem de Teradata Unity y las interacciones entre ellos.

El curso ha sido interesantísimo y el monitor, además de saber un montón, ha resultado ser un tipo encantador.

Teradata Unity implementation workshop

Teradata Unity implementation workshop

Una semana muy bien aprovechada…

Saludos.

Carlos.


Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 62 seguidores