martes, 5 de marzo de 2013

Entendiendo Transacciones con PostgreSQL.

Hay operaciones en los sistemas de bases de datos (DBMS) que no pueden expresarse como una única operación SQL sino como el resultado de un conjunto de dos o más operaciones SQL, cuyo éxito depende de que cada una de esas operaciones se ejecute correctamente ya que si una de ellas falla se considera que toda la operación fallo.
El control de transacciones es una característica fundamental de cualquier DBMS (como PostgreSQL,MS SQL Server ú Oracle) esto permite agrupar un conjunto de operaciones o enunciados SQL en una misma unidad de trabajo discreta , cuyo resultado no puede ser divisible ya que solo se considera el total de operaciones completadas, si hay una ejecución parcial el DBMS se encarga de revertir esos cambios para dejar la información consistente.

Una transacción tiene cuatro características esenciales conocidas como el acrónimo ACID:

  • Atomicity(Atomicidad): Una transacción es una unidad atómica o se ejecutan las operaciones múltiples por completo o no se ejecuta absolutamente nada, cualquier cambio parcial es revertido para asegurar la consistencia en la base de datos.
  • Consistency (Consistencia): Cuando finaliza una transacción debe dejar todos los datos sin ningún tipo de inconsistencia, por lo que todas las reglas de integridad deben ser aplicadas a todos los cambios realizados por la transacción, o sea todas las estructuras de datos internas deben de estar en un estado consistente.
  • Isolation (Aislamiento o independencia): Esto significa que los cambios de cada transacción son independientes de los cambios de otras transacciones que se ejecuten en ese instante, o sea que los datos afectados de una transacción no están disponibles para otras transacciones sino hasta que la transacción que los ocupa finalice por completo.
  • Durability (Permanencia): Después de que las transacciones hayan terminado, todos los cambios realizados son permanentes en la base de datos incluso si después hay una caída del DBMS.

Las transacciones en PostgreSQL utilizan las siguientes palabras reservadas:

BEGIN: Empieza la transacción

SAVEPOINT [name]: Le dice al DBMS la localización de un punto de retorno en la transacción si una parte de la transacción es cancelada. El DBMS guarda el estado de la transacción hasta este punto.

COMMIT: Todos los cambios realizados por las transacciones deben ser permanentes y accesibles a las demás operaciones del DBMS.

ROLLBACK [savepoint]: Aborta la actual transacción todos los cambios realizados deben ser revertidos.


Para poner en práctica estos comandos utilizaremos dos tablas relacionadas Invoices y InvoiceDetails.

Agregamos un par de registros, cada uno dentro de una transacción en el primer registro el commit (confirmación) se realiza de forma automática al terminar la transacción con el comando END.

En el segundo registro utilizamos el comando COMMIT de forma explicita para hacer los cambios permanentes.
Ahora insertamos un nuevo registro y eliminamos un par pero en vez de confirmar la transacción con COMMIT deshacemos los cambios y regresamos los registros a su estado original, utilizando ROLLBACK.
Aquí otro ejemplo del uso de ROLLBACK.

En el siguiente bloque de PL/SQL anónimo vamos a utilizar los comandos anteriores además del comando SAVEPOINT el cuál permite deshacer parcialmente los cambios hechos dentro de una transacción y no toda la transacción por completo.
Persistimos entonces solo los cambios antes del SAVEPOINT, los cambios realizados después serán revertidos por el comando ROLLBACK.

martes, 19 de febrero de 2013

Nuevo número de la revista ATIX de divulgación del software libre (número 21)

Ya se encuentra en línea, el nuevo número de la revista Atix de divulgación del software libre.

Los mirrors para la descarga gratuita se encuentran en este enlace.

El código fuente del tutorial de la revista se publico en la revista se encuentra en este post.

lunes, 18 de febrero de 2013

Trabajando con Binary Large Object (BLOB) en PostgreSQL con GTK# y MonoDevelop II

En el número 20 de la revista Atix se publicó acerca de como leer y escribir datos binarios en PostgreSQL con C#, ahora en este documento complementamos la información anterior mostrando un programa en GTK# que hace uso de los mismos conceptos salvo que ahora los integra con las capacidades ofrecidas por Monodevelop para la creación de formularios GTK#.

Fig. 1 Monodevelop proyecto GTK#

Fig. 2 Diseño del formulario

Fig. 3 Muestra de la solución

Fig. 4 La aplicación ejecutándose

Fig. 5 Consulta de un registro

Fig. 6 Alta de un registro

domingo, 27 de enero de 2013

Entendiendo cursors (cursores) en PostgreSQL.

Para el manejo de grandes cantidades de datos tanto en PostgreSQL como en otras bases de datos relacionales existe el concepto de cursors (cursores) los cuales representan un resultset (conjunto de datos) que son asociados a una variable, una variable de tipo cursor. Esta variable representa un apuntador hacia una tabla virtual representada por una consulta y su respectivo comando SELECT asociado.

La diferencia entre un comando SELECT no asociado a un cursor y uno asociado, es que en el primero la consulta regresará todos los registros a la vez y si queremos limitar la cantidad de registros para procesar debemos correr la consulta nuevamente agregando WHERE, BETWEEN o cualquier otra instrucción para filtrar los resultados. En el caso del comando asociado a un cursor este nos permite desplazarnos y limitar la cantidad de registros para procesar dentro del resultset sin necesidad de un nuevo comando SELECT.

Como ejemplo tenemos una tabla Books dentro de una base de datos llamada MyBooks, aqui esta el script para su creación.

CREATE TABLE books
(
  bookid serial NOT NULL,
  title character varying(512),
  publishyear smallint,
  isbn character varying(13),
  created date DEFAULT ('now'::text)::date,
  CONSTRAINT books_pkey PRIMARY KEY (bookid)
)
Para mostrar la diferencia entre una consulta sin cursor y una consulta asociada a un cursor, ejecutamos la siguiente consulta.

SELECT  bookid, title, publishyear, isbn, created FROM Books.
Esta consulta nos devuelve el siguiente resultado.

Ahora mostramos los comandos que pueden utilizarse al asociar una consulta a un cursor. Para el trabajo con cursores es necesario que estos se encuentren dentro del ámbito de una transacción. Empezamos con una transacción.

BEGIN;
Declaramos el cursor como una variable de tipo cursor y le asociamos una consulta SQL.
DECLARE mycursor CURSOR FOR SELECT * FROM Books;
Ahora podemos navegar entre los registros del resultset, con el comando FETCH, de este comando la sintaxis es:
FETCH [FORWARD | BACKWARD |  ALL | NEXT]
A continuación unos ejemplos de su utilización.

Obtenemos un par de registros.
FETCH 2 FROM MyCursor;

Obtenemos los siguientes 4 registros y nos desplazamos:
FETCH 4 FROM MyCursor;

Obtenemos 3 registros hacia atrás a partir del último registro.
FETCH BACKWARD 3 FROM MyCursor;

Avanzamos de nuevo y obtenemos los próximos 6 registros:
FETCH FORWARD 6 FROM MyCursor;
Obtenemos el próximo registro

FETCH NEXT FROM MyCursor;
También podemos avanzar de forma negativa con FORWARD -[n] lo que es equivalente a BACKWARD [n].
FETCH FORWARD -10 FROM MyCursor;
Obtenemos todos los registros del cursor:
FETCH ALL FROM MyCursor;
Por último cerramos el cursor y confirmamos (o abortamos) la transacción.
CLOSE MyCursor;
COMMIT;

viernes, 11 de enero de 2013

Trabajando con Binary Large Object (BLOB) en PostgreSQL con MonoDevelop

En la actualidad existen aplicaciones que además de almacenar y procesar datos basados en caracteres, requieren también almacenar y procesar archivos de gran tamaño de tipo binario o texto, tales archivos como los multimedia (gráficas, imágenes, audio, vídeo) o los generados por programas de oficina (documentos, presentaciones, hojas de calculo), para estos casos en el estándar SQL están definidos dos tipos de datos para guardar grandes cantidades de información: el CLOB (CHARACTER LARGE OBJECT) que se utiliza para información de tipo texto y el BLOB (BINARY LARGE OBJECT) que se utiliza para información de tipo binario.

En el último número de la revista Atix dedicada a divulgar acerca del software libre, escribí un breve tutorial acerca de como escribir y leer este tipo de datos binarios en PostgreSQL mediante un programa C# construido con Monodevelop.

En la página web de la revista Atix, están los enlaces para descargar la revista en PDF. Abajo pongo el enlace del código fuente para el ejemplo del tutorial.

sábado, 29 de diciembre de 2012

Trabajando con tipos binarios BLOB (Binary Large Object ) en PostgreSQL.

En el estándar SQL están definidos dos tipos de datos para guardar grandes cantidades de información, el CLOB (CHARACTER LARGE OBJECT) que se utiliza para información de tipo texto y el BLOB (BINARY LARGE OBJECT).

El tipo de datos CLOB se representa en la base de datos como un registro con una gran cantidad de información de tipo carácter, estos caracteres pertenecen al conjunto de caracteres definidos por la base de datos (generalmente ASCII) siendo de un solo byte por lo que se utiliza para guardar archivos de texto como por ejemplo los archivos XML. Por su parte el tipo de datos BLOB se representa como un registro de una gran cantidad de información binaria sin estructura distribuida de forma aleatoria por lo que es ideal para archivos binarios como los mapas, las gráficas, y todos los archivos multimedia.

Trabajando tipos de datos BLOB con funciones predeterminadas de PostgreSQL

PostgreSQL proporciona el soporte para tipos de datos BLOB mediante las funciones predeterminadas: lo_import() y lo_export(), las cuales importan y exportan archivos desde el sistema de archivos hacia la base de datos y viceversa. Para ejemplificar el uso de estas funciones tenemos una tabla llamada Books con el siguiente script SQL:

Es esta tabla la columna picture tiene un tipo de dato oid el cual es un identificador que se utiliza como referencia hacia la tabla de sistema pg_largeobject la cual almacena el objeto binario en una o más filas, por lo que la columna picture almacena únicamente el apuntador hacia la información del objeto binario no el objeto binario en si. Como ejemplo agregamos un registro a la tabla, importando la imagen desde el sistema de archivos hacia la base de datos con la función: lo_import()

Ahora recuperamos el registro obteniendo la imagen desde la base de datos hacia el sistema de archivos con la función lo_export().

Las funciones lo_import() y lo_export() son ejecutadas directamente por el servidor de PostgreSQL por lo que la ruta completa del archivo debe tener los permisos correspondientes para ser accesibles desde el servidor, es necesario que el usuario de PostgreSQL tenga el rol de superuser de PostgreSQL (no confundir con el root de Linux).

viernes, 14 de diciembre de 2012

Algoritmo Genético para el TSP (Traveling Salesman Problem) con Monodevelop utilizando C#

La computación evolutiva es una parte de la inteligencia artificial donde se agrupan diferentes técnicas adaptativas enfocadas a encontrar las mejores soluciones para resolver problemas de optimización, estas técnicas parten de una de las principales ideas que existen en la teoría de la evolución biológica propuesta por Charles Darwin, la selección natural es el proceso histórico de transformación de unas especies en otras especies descendientes e incluye la extinción de la gran mayoría de las especies que han existido, lo que es sin duda un problema de optimización además de que muchos de los términos que utiliza la computación evolutiva son tomados de la biología, con la advertencia de que se son usados para representar más o menos la misma idea biológica lo que no equivale a que sean iguales.

La computación evolutiva se compone por las siguientes técnicas:

  1. Programación evolutiva: Son una estrategia de optimización estocástica hacen un énfasis específico en los operadores genéticos tal y como se observan en la naturaleza.
  2. Estrategias evolutivas: Esta técnica esta básicamente enfocada hacia la optimización. En esencia son métodos estocásticos con paso adaptativo, que permiten resolver problemas. A este método se le han agregado procedimientos propios de la computación evolutiva, que lo han convertido en un paradigma más de dicha metodología.
  3. Algoritmos genéticos: Usan métodos que tienen analogía en la selección natural y la evolución.
Entre los usos de la computación evolutiva se encuentran la planificación, el diseño de sistemas, la simulación, el reconocimiento de patrones, el control y la clasificación de datos.

La alternativa para una solución de problemas de planificación y de optimización donde la mayoría están se ubican dentro de la categoría de los problemas NP los cuales no pueden ser resueltos usando las técnicas convencionales y solo pueden ser atacados desde las técnicas de computación evolutiva donde el dominio de esos problemas le corresponden a los algoritmos genéticos (John H. Holland, 1975) 

Como ejemplo de este tipo de aplicaciones me encontré en este web site (http://www.heatonresearch.com) un Applet Java, que utiliza algoritmos genéticos para obtener una solución optima al problema del agente viajero (Traveling Salesman Problem), en el mismo web site el autor nos hace un resumen del problema.

Pues bien como un ejercicio de aprendizaje, traduje el código del applet de Java a C# como un proyecto de Monodevelop utilizando Winforms, a continuación algunas screenshots y el código fuente del proyecto. He de aclarar que debido a la falta de tiempo hice casi copia tal cuál del código, modificando las partes de Java que el compilador me marcaba como errores.

Inicio de la aplicación

Aplicación en ejecucción

Resultado de la aplicación

En su web site el autor Jeff Heaton además del código fuente del applet, ofrece libros acerca de inteligencia artificial y de programación con Java y C#.