MVCC: Control de Concurrencia para Múltiples Versiones de PostgreSQL

El sistema de base de datos PostgreSQL integra un sistema de control de concurrencia para múltiples versiones, en principio. Esto no es más que un sistema que se encarga de mantener copias sobre los datos de forma paralela, para acelerar el sistema de escritura de datos a disco duro, haciendo un control de concurrencia entre las distintas versiones que se van escribiendo.

El problema que intenta solucionar este sistema es el siguiente. Imagina que tenemos un sistema que hace múltiples escrituras y lecturas de una base de datos. No es difícil, seguro que conoces cientos de sistemas que lo hacen. Ahora, ten en cuenta que, los accesos a base de datos, depende para qué, realizan ciertos bloqueos, para asegurarse de que la información a modificar o a leer (incluso) no es modificada por nadie, hasta que termine su actividad.

En MySQL, por ejemplo, existen distintos tipos de bloqueos, muchos de ellos automáticos, que hacen el bloqueo de una tabla completa, o de ciertas partes específicas, al hacer una actividad de modificación, o un bloqueo compartido, para hacer actividades de lectura (solo bloquea en este caso a los que intentan escribir).

Pero en tema de índices, hay muchos SGBD que usan sistemas de índices que al actualizarse, se bloquean completamente, dejando, no solo las escrituras bloqueadas, sino también las lecturas, creando un lag de acceso a los datos.

Interbase fue la primera base de datos que eliminó la contención, los deadlocks y garantizaba transacciones ACID mediante el sistema MVCC. La idea es: no actualizar ni eliminar nunca una fila del disco. Si deseas actualizar, se agrega una nueva fila con la misma clave primaria, la cual oculta la antigua fila. Si deseas eliminar, agrega una nueva fila que etiqueta la clave primaria como eliminada, la cual oculta la antigua fila.

Las viejas filas no eran nunca actualizadas, así que no era necesario implementar ningún sistema de bloqueo y la contención (o espera) mágicamente desapareció.

El sistema, no obstante, tiene pequeños defectos: usa más espacio de disco y puede ser algo más lento a la hora de leer datos. La buena noticia es que los datos se pueden respaldar (realizarse un backup) en cualquier momento sin bloquear el sistema.

En MySQL, los tipos de tablas Falcon (a partir de la versión 6.0) e InnoDB (antes de la 6.0), implementan este sistema para las actualizaciones (updates) usando bloqueo a nivel de fila, lo cual puede causar un tiempo de espera para otros procesos (contención).

En PostgreSQL se usa el comando VACUUM para actualizar las base de datos, es decir, implementar las transacciones agregadas al final en lugar de a las que reemplazan y eliminar las tuplas marcadas para reclamar más espacio en disco. Esta operación demora, pero hace que la base de datos pase de un consumo alto de disco duro, al ajustado que debe de ser, antes de la próxima sesión crítica :-)

Hay otras bases de datos que también implementan Multiversion concurrency control, tal y como menciona la wikipedia, tales como:

  • Berkeley DB: que es una base de datos a nivel de fichero, como puede ser SQLite, pero sin uso del lenguaje SQL.
  • CouchDB: de la cual ya comenté algunas cosas en otro artículo.
  • Oracle 7: y superiores.
  • Microsoft SQL Server 2005: y superiores. El soporte es opcional, se pueden configurar los niveles de aislamiento (isolation) para poder usar MVCC o no.
  • MySQL: a través de InnoDB o Falcon, pero se usa nivel de bloqueo por fila, en lugar de snapshot.

Más información: