You are on page 1of 21

Replicacin en PostgreSQL 9.

Trabajo de Investigacin

Universidad Nacional de Salta Facultad de Ciencias Exactas Base de Datos II Segundo Cuatrimestre 2012 Martnez Moreno, Germn Ren

Concepto de Replicacin
La replicacin es el proceso de intercambiar datos de transacciones para asegurar la consistencia entre nodos de bases de datos redundantes. Es el proceso de copiar y mantener los elementos de una base de datos en mltiples bases de datos que forman un sistema de bases de datos distribuido. Entre las distintas ventajas que ofrece este proceso encontramos: Alta disponibilidad (high availability): Se puede incrementar la disponibilidad de una base de datos mediante la replicacin en un sistema distribuido. Si una de las mquinas del sistema falla, las otras podrn satisfacer las necesidades del cliente. Balance de carga (load balancing): La replicacin se puede utilizar para hacer un balance de carga. sta es una tcnica usada para compartir el trabajo a realizar entre varias computadoras. Soporte para aplicaciones de alto consumo: Se puede satisfacer las necesidades de ciertos clientes que requieren un alto consumo en consultas, que sera muy costo en rendimiento, o hasta imposible, en una base de datos sin replicacin. Confiabilidad: Debido a que existen varias copias de los datos disponibles en el sistema, se cuenta con un mecanismo confiable de recuperacin de datos ante fallos en algn nodo. Los servidores de bases de datos de slo lectura son relativamente fciles de combinar, ya que los datos de slo lectura deben ser almacenados slo una vez en cada servidor. Sin embargo, la mayora de los servidores de bases de datos tienen consultas variadas de lectura y escritura. Este tipo de servidores son mucho mas difciles de combinar debido a que una consulta de escritura hecha a un servidor debe poder actualizar el resto de los servidores para que en las prximas consultas puedan entregar datos consistentes. Con la replicacin surgen los problemas de sincronizacin. Existen distintos modelos que dan solucin a este problema, cada uno lo enfoca de manera distinta. Replicacin sncrona: una transaccin de modificacin de datos no es considerara hasta que todos los servidores confirmaron la transaccin. Esto garantiza que ante un eventual error en la transaccin no se perdern datos y que todos los servidores de carga balanceada devolvern resultados consistentes sin importar cual de los servidores haya sido consultado. Replicacin asncrona: permiten un retraso entre el momento en que se realiza una consulta y el tiempo de propagacin a los otros servidores. Aqu existe la posibilidad de que algunas transacciones se pierdan cuando se cambia a un servidor de respaldo y que los servidores de carga balanceada devuelvan resultados ligeramente antiguos. La comunicacin asncrona es utilizada cuando la comunicacin sincrnica sera muy lenta. Algunas soluciones permiten modificar los datos solo a un servidor. A este servidor se lo conoce como servidor de lectura/escritura (read/write server), primario (primary server), o maestro (master server). Los servidores que rastrean los cambios del maestro son llamados servidores de reserva (standby servers), o esclavos (slave servers). Un servidor de reserva que no puede ser conectado hasta que sea ascendido al nivel de servidor maestro se llama servidor en espera semiactiva (warm standby server) y uno que acepta conexiones y sirve a consultas de slo lectura es llamado servidor de reserva caliente (hot standby server).
2 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Modelos de Replicacin de Datos


Shared Disk Failover Este mtodo evita el sobrecargo de sincronizacin utilizando una sola copia de la base de datos. Usa un arreglo de disco simple que es compartido por mltiples servidores. Si el servidor principal de la base de datos falla, el servidor standby es capaz de montarse y empezar la base de datos como si se tratase de una recuperacin de una cada de la base de datos. Esto permite una recuperacin rpida y sin prdida de datos. File System Replication Una versin modificada de la funcionalidad del hardware compartido es la replicacin del sistema de archivos, donde todos los cambios de dicho sistema estn duplicados en el sistema de archivos de otra computadora. La nica restriccin es que la duplicacin debe ser hecha de manera tal que se asegure que el servidor standby tiene una copia consistente del sistema de archivos. Transaction Log Shipping Los servidores warm standby y hot standby pueden mantenerse actualizados leyendo un flujo de registros de WAL (write-ahead log). Si el servidor principal falla, el servidor standby contiene casi todos los datos del servidor pincipal, y puede ser rpidamente convertido en el nuevo servidor master. Este modelo puede ser sincrnico o asincrnico, y slo puede ser implementado para el servidor de base de datos completo. Trigger-Based Master-Standby Replication Este tipo de replicacin enva todas las consultas de modificacin de datos al servidor master. El servidor master enva asincrnicamente las modificaciones de los datos al servidor standby. ste ltimo puede responder consultas de slo lectura mientras el servidor master esta corriendo. Statement-Based Replication Middleware Con este tipo de replicacin, un programa intercepta todas las consultas SQL y las enva a uno o todos los servidores. Cada servidor opera independientemente. Las consultas de lectura-escritura deben ser enviadas a todos los servidores, as todos los servidores reciben cualquier cambio efectuado. Pero las consultas de slo lectura pueden ser enviadas a un nico servidor, permitiendo la distribucin de carga de trabajo de lectura a travs de los servidores disponibles. Asynchronous Multimaster Replication Para los servidores que no estn conectados regularmente, mantener los datos consistentes a travs de estos es un gran desafo. Usando este tipo de replicacin, cada servidor trabaja de manera independiente y peridicamente se comunica con los otros servidores para identificar las transacciones conflictivas. Estos conflictos pueden ser resueltos por el usuario o por reglas de resolucin de conflictos. Synchronous Multimaster Replication En este tipo de replicacin, cada servidor puede aceptar solicitudes de escritura y los datos modificados son transmitidos desde el servidor original al resto de los servidores antes de que cada transaccin sea confirmada. Una fuerte actividad de escritura puede causar un bloqueo excesivo, causando un bajo rendimiento. Las solicitudes de lectura pueden ser enviadas a cualquier servidor.

3 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Replicacin nativa en PostgreSQL


A partir de la versin 9.0 de PostgreSQL, se incluye la funcin de replicacin como parte de su ncleo. El modelo que se implementa es el Transaction Log Shipping, conocido como: Streaming Replication con la opcin Hot Standby, que permite que el/los servidores standby puedan responder consultas de slo lectura. Ficheros WAL Los ficheros WAL (Write Ahead Log) son utilizados por PostgreSQL para guardar toda la informacin sobre las transacciones y cambios realizados en la base de datos. Son utilizados para garantizar la integridad de los datos almacenados en la base de datos. Tambin se utilizan para reparar automticamente posibles inconsistencias en la base de datos despus de una cada del servidor. Estos ficheros tienen un nombre nico y un tamao por defecto de 16 Mb. Cada vez que ocurre una transaccin en la base de datos, se escribe en uno de estos archivos, as, si hay algn problema, se puede recurrir a los archivos WAL para recuperar dicha transaccin. Streaming Replication con Hot Standby Este tipo de replicacin es asincrnica, entre un servidor master y uno o varios servidores standby. Se basa en la transferencia de registros WAL (no de archivos completos), lo que permite mantener una copia bastante actualizada del servidor. Funciona de la siguiente manera: El servidor master tiene un procedimiento llamado WALSender, que se encarga de enviarle el registro WAL a los servidores standby. Cada servidor standby tiene un procedimiento WALReceiver que recibir el registro WAL enviado por el servidor master. La caracterstica Hot Standby permite que el servidor standby responda a consultas de slo lectura, de esta manera se puede balancear la carga del servidor master distribuyendo las consultas a los otros servidores. Existe un problema con esta solucin y es que hay que tener cuidado de que los archivos WAL en el servidor master no sean reciclados antes de ser enviados al servidor standby. No deberamos preocuparnos por esto si disponemos de suficiente espacio para tener un gran nmero de archivos WAL (incrementar el nmero de wal_keep_segments, cada uno necesita 16 Mb) y/o la base de datos no es muy activa. En caso de que no se pueda asegurar eso, se puede complementar la replicacin con una solucin conocida como File-based Log Shipping, (implementada de forma nativa desde PostgreSQL 8.3), que consiste en el envo peridico de archivos WAL al servidor standby. Tambin se podra optar por la solucin File-based Log Shipping sin utilizar Stramig Replication, pero ante una cada del servidor principal se pueden perder las ltimas transacciones realizadas. Por lo tanto, la manera de realizar un sistema de replicacin robusto es utilizando una combinacin de ambas soluciones, como vemos en la siguiente imagen y como vamos a utilizar en el ejemplo de implementacin.
4 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Sistema de replicacin utilizando Streaming Replication y File-based Log Shipping.

How to Streamin Replication/Hot Standby Para el desarrollo de un ejemplo de aplicacin de replicacin en PostgreSQL, vamos a utilizar dos mquinas con las siguientes caractersticas: Nodo Servidor: Procesador AMD Athlon X2 5600 Memoria 2 GB DDR2 Disco rgido 500 GB Sistema Operativo: GNU/Linux Ubuntu 12.10 64 bits. IP de red: 192.168.0.20 Nodo Standby: Procesador Intel Pentium Dual Core T4500 Memoria 4 GB DDR3 Disco Rgido 500 GB Sistema Operativo: GNU/Linux Ubuntu 12.10 64 bits. IP de red: 192.168.0.21 Versin en ambos nodos: PostgreSQL 9.2 Directorio de instalacin de PostgreSQL en ambos nodos: /opt/PostrgeSQL/9.2/ Directorio de datos de PostgreSQL en ambos nodos: /opt/PostrgeSQL/9.2/data/ Debemos tener instalado OpenSSH Server en ambos nodos. Se utiliza una conexin wi-fi con un router Motorola SBG901 de Fibertel. Si bien, por motivos de eficiencia en la velocidad de conexin no es recomendable utilizar redes inalmbricas, para este ejemplo la vamos a utilizar por cuestiones prcticas.
5 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

En el servidor master est instalada la base de ejemplo northwind y una base de prueba llamada prueba01. Es importante saber que Streaming Replication no nos permite elegir la base de datos a replicar, por lo tanto, si hubiese otras bases en el nodo master tambin se replicaran. Lo primero que debemos hacer es detener el servicio de PostgreSQL en el servidor esclavo: sudoservicepostgresql9.2stop Creamos una carpeta en el servidor standby que servir para que el servidor master transfiera los archivos WAL completos. Estar en el directorio raz y el propietario ser postgres: sudomkdir/wal sudochownpostgres:postgres/wal Cambiamos el propietario de la carpeta de instalacin de PostgreSQL en ambos servidores: sudochownRpostgres:postgres/opt/PostgreSQL/ Ahora nos identificamos como el usuario postgres en el servidor maestro para crear el par de claves privadas y pblicas: sudosupostgres sshkeygentdsa Ahora en el servidor esclavo le damos una contrasea temporal al usuario postgres: sudopasswdpostgres Desde el servidor maestro, identificados como postgres hacemos: sshcopyidi/opt/PostgreSQL/9.2/.ssh/id_dsa.pub postgres@192.168.0.21 que instala la credencial en el servidor esclavo. Nos pedir la contrasea de postgres que le pusimos en el paso anterior. Ya le podemos quitar la contrasea a postgres: sudopasswdlpostgres Creamos en el servidor standby un archivo llamado recovery.conf que debe ser guardado dentro de la carpeta data de la instalacin de PostgreSQL (/op/PostgreSQL/9.2/data en nuestro caso) y que contendr lo siguiente: restore_command='cp/wal/%f%p' standby_mode=on primary_conninfo='host=192.168.0.20port=5432user=postgres'
6 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

En el archivo postgresql.conf del servidor esclavo habilitamos la opcin de Hot Standby: hot_standby=on En el archivo pg_hba.conf del servidor master, aadimos la siguiente linea que habilita al usuario postgres para hacer Streaming Replication: host replication postgres 192.168.0.21/32 trust

En el servidor maestro, configuramos el archivo postgresql.conf de la siguiente manera: listen_addresses=* wal_level=hot_standby archive_mode=on archive_command='scp%p192.168.0.21:/wal/%f' max_wal_senders=1 wal_keep_segments=1000 Reiniciamos el servicio en el maestro: sudoservicepostgresql9.2restart Ahora procedemos a crear lo que se conoce como bakup binario en el servidor maestro. Nos identificamos como usuario postgres y accedemos a psql: sudosupostgres /opt/PostgreSQL/9.2/bin/psql En psql iniciamos el backup: selectpg_start_backup('backupbinario'); Ahora copiamos los archivos del servidor maestro al esclavo, excepto los archivos de configuracin:
rsynca/opt/PostgreSQL/9.2/192.168.0.21:/opt/PostgreSQL/9.2/ excludepostmaster.pidexclude'*.conf'excludepostmaster.opts

En psql de nuevo, detenemos el bakcup: selectpg_stop_backup(); Ya terminamos, solo resta iniciar el servicio de PostgreSQL en el nodo esclavo: sudoservicepostgresql9.2start

7 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Comprobando funcionamiento A continuacin, una serie de capturas de pantalla que nos muestran que el sistema de replicacin funciona correctamente: El escritorio con entorno GNOME 3 es el maestro y el de Unity es el esclavo.

Las bases de datos en el servidor maestro.

8 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Las bases de datos replicadas en el servidor esclavo.

9 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Viendo los datos en la tabla01 de la base de datos prueba01 en el servidor master.

10 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Los datos de tabla01 en la base prueba01 que est en el standby coinciden con los del master.

11 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Insertamos en tabla01 una fila con id = 10 y valor = 16. Se produjo la transaccin con xito.

12 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Como esperbamos, la tupla ingresada anteriormente se ve reflejada en la rplica.

13 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Intentamos ingresar una tupla en el servidor esclavo y no nos permite porque solo responde consultas de slo lectura (Hot Standby).

14 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Replicacin en PostgreSQL con Slony-I


Slony-I es un sistema de replicacin asncrona para PostgreSQL del tipo Master Multi Slave. Realiza las actualizaciones a travs de disparadores o triggers. Algunas de las caractersticas de Slony-I son: Puede replicar datos entre diferentes versiones de PostgreSQL. Puede replicar datos entre servidores con distinto hardware o sistemas operativos. Permite seleccionar qu tablas replicar. Permite elegir en qu servidor esclavo se replicarn las tablas.

Slony-I tambin est disponible para versiones de PostgreSQL inferiores a la 9.0. Esta solucin, al estar basada en triggers presenta ciertas restricciones. Entre las limitaciones de Slony-I tenemos que no puede replicar automticamente: Cambios realizados por una consulta DDL. Cambios realizados a usuarios y roles. Cambios en BLOB (Binary Large OBject Objeto grande binario)

Ejemplo sencillo de aplicacin. En este ejemplo voy a trabajar sobre la plataforma Windows 7, para no tener que cambiar la configuracin que hice para Streaming Replication. Las IP de red siguen siendo las mismas (192.168.0.20 y 192.168.0.21) y la versin del software es PostgreSQL 9.1. Para instalar Slony-I, vamos a utilizar Stack Builder. El proceso de instalacin es muy sencillo e intuitivo.

Instalacin de Slony-I con Stack Builder. Los otros pasos los indica el instalador.

15 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Vamos a replicar la base de datos baseslony que est en el servidor master y que cuenta con dos tablas: localidades y provincias. Utilizaremos el super usuario postgres, aunque no es necesario que el usuario tenga privilegios de super. Ambos nodos deben tener la misma base de datos antes de hacer la replicacin. Desde el pgAdmin vamos a File Options General y en Slony-I Path especificamos el directorio donde se instal y aceptamos. Ahora debemos editar el archivo pg_hba.conf en el maestro y en el esclavo: #Maestro host #Esclavo host all all all all 192.168.0.20/32 192.168.0.21/32 md5 md5

Aadimos una excepcin al firewall de Windows para el puerto 5432 en cada una de las mquinas para permitir que se comuniquen. Ahora debemos crear un par de scripts que utilizamos para indicar qu tablas queremos replicar y cul ser el nodo maestro y cul el esclavo. Son los siguientes dos archivos de texto: Maestro.txt:
clustername=pruebaSlony2; node1adminconninfo='dbname=baseslonyhost=192.168.0.20user=postgres password=adminPC'; node2adminconninfo='dbname=baseslonyhost=192.168.0.21user=postgres password=adminPC'; initcluster(id=1,comment='NodoMaestro'); createset(id=1,origin=1,comment='Tablas'); setaddtable(setid=1,origin=1,id=1,fullyqualified name='public.provincias',comment='Tablaprovincias'); setaddtable(setid=1,origin=1,id=2,fullyqualified name='public.localidades',comment='Tablalocalidades'); storenode(id=2,comment='NodoEsclavo',EVENTNODE=1); storepath(server=1,client=2,conninfo='dbname=baseslonyhost=192.168.0.20 user=postgrespassword=adminPC'); storepath(server=2,client=1,conninfo='dbname=baseslonyhost=192.168.0.21 user=postgrespassword=adminPC'); storelisten(origin=1,provider=1,receiver=2); storelisten(origin=2,provider=2,receiver=1);

16 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Esclavo.txt:
clustername=pruebaSlony2; node1adminconninfo='dbname=baseslonyhost=192.168.0.20user=postgres password=adminPC'; node2adminconninfo='dbname=baseslonyhost=192.168.0.21user=postgres password=adminPC'; subscribeset(id=1,provider=1,receiver=2,forward=yes);

Estos scripts deben ser guardados en el directorio C:\Program Files\PostgreSQL\9.1\bin, el Maestro.txt en el del servidor master y el Esclavo.txt en el del servidor standby. Ahora ejecutamos el script en el nodo maestro con el siguiente comando: C:\Program Files\PostgreSQL\9.1\bin\slonic Maestro.txt Esperamos unos segundos y verificamos que no existan errores. Si todo sali bien, abrimos el pgAdmin y dentro de la base de datos baseslony, en Slony Replication ya nos debe aparecer el cluster pruebaSlony2. Ejecutamos el script del servidor esclavo: C:\Program Files\PostgreSQL\9.1\bin\slonic Esclavo.txt Ahora tenemos que iniciar la replicacin en cada nodo. Para ello, primero vamos al servidor maestro y, desde la ruta de la carpeta bin de PostgreSQL ejecutamos el siguiente comando: slon pruebaSlony2 dbname = baseslony user = postgres password = adminPC Luego ejecutamos la misma linea desde el nodo esclavo. En mi caso especial, tuve que descargar la librera pthreadVC2.dll y agregarla en la carpeta /bin porque estaba ausente. Ya est en funcionamiento la replicacin. Esta se mantendr funcionando siempre que no se cierren las consolas en las que ejecutamos la ltima linea. Cada vez que iniciemos el servicio de PostgreSQL debemos volver a ejecutar ese comando. Veamos cmo funciona:

17 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Agregamos la localidad Santa Maria en el maestro.

En menos de 30 segundos aparece en el esclavo la localidad agregada.

18 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Ventajas frente a la replicacin nativa Interfaz visual que permite configurarlo de manera ms intuitiva. Independiente de la plataforma de los nodos. Permite seleccionar qu bases de datos se replicarn. Permite seleccionar qu tablas de la base de datos se replicarn.

Desventajas frente a la replicacin nativa No replica cambios efectuados por consultas DDL. No replica cambios en los usuarios ni en los roles. No puede repicar automticamente cambios a BLOBs. Es necesario instalar software adicional.

Replicacin en PostgreSQL con RubyRep


RubyRep es una herramienta de replicacin asincrnica, basada en Ruby que permite crear sistemas de replicacin de tipo Master Master y Master Slave. RubyRep tiene soporte tanto para PostgreSQL como para MySQL, es independiente de las versiones de las bases de datos y de la plataforma (funciona tanto en Linux como en Windows, aunque en Windows puede tener un rendimiento menor). Estas caractersticas hacen de RubyRep una herramienta muy flexible que permite la integracin de distintos sistemas. Es fcil de instalar, configurar y monitorear. Tambin es independiente del diseo que tengan las tablas a replicar, es decir, permite tablas con claves primarias simples, combinadas, o incluso sin claves primarias (en este ltimo caso es necesario que exista al menos una columna Unique). Adems puede procesar con xito textos multi-byte y tipos de datos grandes: en PostgreSQL con bytea y text, en MySQL funciona con los BLOB y text. Puede encontrar nuevas tablas aadidas en uno de los nodos y automticamente sincronizar su contenido. Tambin puede configurar de manera automtica disparadores o triggers, tablas de log, etc. Algunas de sus limitaciones son que no permite realizar un balance de carga, no admite lo que se conoce como Connection Pooling (agrupamiento de conexiones), y no puede realizar particionamiento de consultas. Ventajas frente a la replicacin nativa Independiente de plataformas y de versiones de bases de datos. Puede ser usado en PostgreSQL y en MySQL. Permite la replicacin Multi Master.

Desventajas frente a la replicacin nativa Es necesario instalar software adicional. Menor rendimiento.
19 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Conclusiones
Un sistema de replicacin es muy importante para una organizacin que cuenta con informacin sensible, para aquellas que manejan grandes volmenes de datos, o para las que utilizan acceso remoto a la informacin. Contar con un sistema de replicacin apropiado va a depender de muchos factores, por lo que es necesario definirlos previamente y que la persona que se va a encargar de implementarlo est bien informado sobre todas las soluciones que ofrece el mercado. Como podemos ver en el siguiente cuadro, existe una gran variedad de alternativas:

Es importante tambin destacar que el desarrollo de PostgreSQL est empezando a incluir ms caractersticas de replicacin a medida que salen las nuevas versiones. Un breve repaso de cmo se empez a incluir estas caractersticas nativamente: PostgreSQL 8.3 Warm Standby PostgreSQL 9.0 Hot Standby / Streaming Replication PostgreSQL 9.1 Replicacin sincrnica ( Master Slave). Seguramente en prximas versiones de este motor se incluirn algunas nuevas caractersticas o se mejorarn las ya implementadas.

20 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

Webs consultadas
Replicacin Nativa http://www.postgresql.org/docs/9.2/static/high-availability.html http://www.postgres-r.org/documentation/terms http://www.corporacionsybven.com/portal/index.php? option=com_content&view=article&id=384:replicacion-de-datos&catid=124:conceptos-teoricos http://es.scribd.com/doc/70420722/REPLICACION http://www.postgresql.org.es/node/483 http://www.themagicnumber.es/replication-in-postgresql-i?lang=es http://www.themagicnumber.es/replication-in-postgresql-ii-hot-standbystreaming-replication? lang=es http://wiki.postgresql.org/wiki/Streaming_Replication http://www.howtoforge.com/how-to-set-up-a-postgresql-9.0-hot-standby-streaming-replication-serv er-with-repmgr-on-opensuse-11.4 http://wiki.postgresql.org/wiki/Binary_Replication_Tutorial Slony-I http://slony.info/documentation/2.1/index.html http://www.howtoforge.com/configuring-slony-i-cascading-replication-on-postgresql-8.3 http://www.slideshare.net/JohannaMendez2/replicacion-con-postgresql-y-slony http://basesdedatosues.blogspot.com.ar/2010/06/replicacion-postgresql-slony-i.html RubyRep http://www.rubyrep.org http://www.rubyrep.org/features.html http://www.slideshare.net/denishpatel/yet-another-replication-tool-rubyrep http://wiki.postgresql.org/wiki/Replication,_Clustering,_and_Connection_Pooling

21 U.N.Sa. - Base de Datos II 2012 Martnez Moreno, Germn Ren

You might also like