viernes, 27 de abril de 2007

Generar spools de más de 2 Gigas en Unix

Hay varias formas de generar spools con sql*plus desde Unix. La forma tradicional (o directa) es escribir un shell que realice lo siguiente:

-Invocar a sql*plus en modo embebido.
-Ejecutar spool y realizar el SELECT.
-Finalizar el spool con spool off.
-Salir de sql*plus.
-Zipear el archivo de salida (recomendado si se va a enviar a otro destino).

El problema que presenta este enfoque, es que en algunos sistemas operativos, puede existir el límite de 2 Gigas de tamaño para archivos, por lo cual nuestro script va a alimentar el spool hasta llegar a ese tamaño. En el mejor de los casos obtendremos un error inesperado, en otros quizás ni nos enteremos.

Una forma alternativa (y para mi gusto más elegante), es utilizar el comando mknod de Unix. Este comando, entre otras funcionalidades, permite crear un pipe de tipo FIFO que funciona como un dispositivo que utiliza el buffer del sistema operativo y permite conectarlo directamente con un programa de compresion como compress o gzip, evitando que se utilice el file system para almacenar el spool sin comprimir. También es posible conectarlo al programa split para que particione el archivo zip, si este continúa superando el límite máximo.

Básicamente las tareas que hay que escribir en nuestro shell son:
-Borrar pipes que hayan quedado anteriormente (puede fallar si ya existe)
-Crear el pipe
-Asignarle permisos al pipe (con chmod)
-Invocar en modo background al programa destino (el que va a recibir el spool). Este podría ser gzip, split, o ambos.
-Invocar a sqlplus para que realice el spool
-Borrar el pipe creado

Resulta poco intuitivo llamar primero al programa destino y luego en definitiva a quien genera el spool, pero veamos un ejemplo de código para visualizarlo más claramente.

Este script genera un spool y lo comprime en un zip:

1   #/bin/ksh
2 rm -f ${ARCHIVO}.pipe 2>/dev/null
3 mknod ${ARCHIVO}.pipe p
4 gzip -f < ${ARCHIVO}.pipe > ${ARCHIVO}.txt.Z 2>>${LOG} &
5 sqlplus -s usuario/password << EOF > /dev/null 2>> ${LOG}
6 spool ${ARCHIVO}.pipe
7 select * FROM user_objects;
8 spool off
9 EOF
10 rm -f ${ARCHIVO}.pipe 2>/dev/null
En la línea 2 eliminamos pipes que hayan podido quedar abiertos por alguna razón. De quedar abierto obtendríamos un error al crearlo de nuevo.

En la línea 3 creamos el pipe. El primer parámetro es el nombre y el segundo el tipo (p=FIFO)

En la línea 4 invocamos en background a gzip (notar el & al final de la linea). El pipe (el cual todavia no ha recibido datos), va a ser la entrada fuente para gzip. Luego gzip generará el archivo .txt.Z.

Las líneas 5 a 8 llaman a sqlplus y comienzan a enviar datos al pipe, luego gzip que esta corriendo en background zipea el contenido, sin necesidad de tener un archivo en file system.

La línea 10 elimina el pipe.

Si el archivo final .zip alcanza los 2 Gigas, vamos a tener el mismo problema, gzip no va a poder crearlo. Es necesario adicionarle el comando split y conectarlo con gzip para que parta el archivo en secciones de un tamaño manejable.
Para eso, hay que insertar entre la línea 3 y la 4 del script anterior, la siguiente línea:

3.5 split -b 1024m < ${ARCHIVO}.txt.Z &

Conviene leer primero la línea 4 y luego la 3.5, observar que ambos programas corren en background.

La línea 4 es la misma, genera el archivo .txt.Z.

La línea 3.5 recibe el archivo .txt.Z y lo divide en archivos de 1024 megas, el tamaño es en bytes (especificado por el parámetro b).

Sea cual sea el programa que genera el archivo, siempre podemos manipular con pipes los datos sin llegar a utilizar un archivo del file system para pasos intermedios.

Próximos pasos:
MAN del comando mknod
MAN del comando split

lunes, 23 de abril de 2007

Ahí Vamos!

Como siempre, hay una primera vez para todo!!
La idea de comenzar mi blog surgió por sugerencia de mi amigo Fede Brubacher, adicto a RoR y otras tecnologías emergentes. El, que me conoce y ha sufrido mi orientación a las bases de datos relacionales, movilizó algunos mecanismos de motivación y curiosidad, con el simple hecho de mostrarme su trabajo:
http://fbrubacher.com/

"Dedicado a aquellos que con sus blogs técnicos me ahorraron tantas horas de trabajo y esfuerzo"

Sin más reflexiones doy por inagurado este blog.

Sobre el autor

Lucio Fernández Herrera
Ingeniero de Sistemas (UDELAR, 2003)
Oracle OCP DBA Certified (2006)
Consultor Oracle Independiente

OCP DBA Certification logo


Perfil Técnico


:: Bases de datos ::
Oracle databases 8i/9i/10g/11g, MySQL, SQL Server

:: Tecnologías ::
Unix, PL/SQL, Apex, Forms, PHP, J2EE, Data Guard, Sun Cluster

:: Áreas de especialización ::
Desarrollo, análisis y diseño, administración, datawarehousing


Me desempeño como DBA y especialista en PL/SQL en proyectos con J2EE. Actualmente resido en Rio de Janeiro, Brasil.
Realizo consultorías de instalación, configuración, administración, tunning, entre otras diversas áreas de desarrollo.
En los diversos proyectos en los cuales he participado aparece un común denominador que es la falta de un conocimiento avanzado de la herramienta que se está utilizando. Esto lleva a efectos tales como la mala performance de los sistemas y sobreesfuerzo de las personas. En ese sentido el propósito de este blog es dar mi pequeño aporte para aliviar y ayudar a que el trabajo sea cada vez más efectivo.
En la carrera de bases de datos, mi motivación es seguir creciendo y aprendiendo día a día en un campo que debe soportar y acompañar a las nuevas tecnologías.

Contactar al autor