Lección 5 de 25 · Lectura y práctica
Evaluación de Conceptos Fundamentales
Tipo de lección: QuizConcepto claveEn PostgreSQL para aplicaciones de alta concurrencia, el MVCC (Multi-Version Concurrency Control) es el mecanismo fundamental que permite multiples transacciones leer y escribir simultaneamente.
Del concepto a la práctica
Taller de esta lección
Esta evaluación conecta MVCC, vacuum, snapshots y observabilidad. Una fila actualizada no se sustituye siempre en el mismo lugar lógico: la versión visible depende del snapshot y las versiones antiguas deben poder limpiarse cuando ninguna transacción las necesita. Por eso una transacción ociosa puede afectar bloat aunque no ejecute consultas continuamente.
Ejemplo resuelto
Una tabla tiene 1.000 filas y se actualizan 100. Tras confirmar, el contador de versiones muertas puede aumentar. Si otra sesión mantiene un snapshot antiguo abierto, VACUUM no puede retirar todas esas versiones. Se registra n_dead_tup antes y después de cerrar la sesión larga.
Mide filas vivas y muertas.
Ejecuta una actualización controlada.
Mantén y luego cierra el snapshot antiguo.
Ejecuta mantenimiento y compara los contadores.
Error frecuente: interpretar VACUUM como borrado inmediato de espacio del sistema operativo. Corrección: distingue reutilización interna de reducción física del archivo.
Abre B con BEGIN ISOLATION LEVEL REPEATABLE READ; SELECT sobre la tabla antes de que A actualice100 filas y confirme. Así el snapshot viejo necesita las versiones anteriores. Un BEGIN sin lectura o una sesión READ COMMITTED inactiva no demuestra ese bloqueo de limpieza. n_dead_tup es una estimación estadística, puede tardar en actualizarse y no es un contador exacto de estas100 versiones. No exijas un número específico; vincula la tendencia a vacuum/snapshot y limita el laboratorio.
Pruébalo
Explica qué cambia si la sesión antigua se cierra antes del mantenimiento y qué métrica observarías para verificarlo.
Comprueba tu resultado
Debes identificar la sesión antigua como impedimento temporal y mostrar que las versiones muertas disminuyen después de cerrar el snapshot y mantener la tabla.

Mapa de prácticaUna clave conecta cada pedido con su cliente. INNER JOIN devuelve las coincidencias y puede producir varias filas por cliente. LEFT JOIN conserva también los clientes sin pedido y representa los campos ausentes con NULL.
Ver la infografía en tamaño completo ↗Tipo de lección: Quiz
Concepto clave
En PostgreSQL para aplicaciones de alta concurrencia, el MVCC (Multi-Version Concurrency Control) es el mecanismo fundamental que permite multiples transacciones leer y escribir simultaneamente sin bloquearse entre si. Imagina una biblioteca donde varios lectores pueden consultar diferentes versiones del mismo libro mientras un escritor actualiza una copia nueva; nadie espera por nadie, y todos ven una version consistente.
El MVCC crea una "instantanea" (snapshot) de los datos al inicio de cada transaccion, almacenando versiones antiguas de las filas modificadas. Esto elimina los bloqueos de lectura, pero introduce desafios como el bloat (datos obsoletos acumulados) y la necesidad de VACUUM para limpiar. En alta concurrencia, entender esto es crucial para evitar degradacion del rendimiento y problemas de almacenamiento.
Como funciona en la practica
Supongamos una aplicacion de reservas de vuelos con miles de usuarios concurrentes. Una transaccion A comienza a las 10:00:00 y lee asientos disponibles. Simultaneamente, una transaccion B inicia a las 10:00:01 y reserva un asiento, actualizando la fila. Con MVCC, la transaccion A sigue viendo la version anterior de los datos (su snapshot), evitando lecturas sucias, mientras B escribe una nueva version. PostgreSQL usa campos ocultos como xmin y xmax para gestionar esto.
Paso a paso: 1) Cada transaccion obtiene un ID unico (XID). 2) Al modificar una fila, se crea una nueva version con xmin igual al XID de la transaccion. 3) Las versiones antiguas se marcan con xmax. 4) Las lecturas ven solo filas donde xmin es visible segun el snapshot. Esto permite alta concurrencia, pero requiere mantenimiento periodico con VACUUM para reclamar espacio.
Codigo en accion
Ejemplo de como el MVCC afecta las consultas en una tabla de alta concurrencia:
-- Crear tabla para simulacion
CREATE TABLE reservas (
id SERIAL PRIMARY KEY,
vuelo_id INT,
asiento VARCHAR(5),
estado VARCHAR(20) DEFAULT 'disponible'
);
-- Insertar datos iniciales
INSERT INTO reservas (vuelo_id, asiento) VALUES (101, 'A1'), (101, 'A2');
-- Transaccion 1: Lectura inicial (snapshot tomado aqui)
BEGIN;
SELECT * FROM reservas WHERE vuelo_id = 101;
-- Resultado: id=1, asiento='A1', estado='disponible'; id=2, asiento='A2', estado='disponible'
-- Transaccion 2: Modificacion concurrente (en otra sesion)
BEGIN;
UPDATE reservas SET estado = 'reservado' WHERE id = 1;
COMMIT;
-- Transaccion 1: Lectura posterior (aun ve el snapshot antiguo)
SELECT * FROM reservas WHERE vuelo_id = 101;
-- Resultado: id=1, asiento='A1', estado='disponible' (version anterior visible)
COMMIT;Refactorizacion para mejorar el manejo de versiones en alta concurrencia:
-- Antes: Consulta sin control de versiones, puede causar bloat rapido
UPDATE reservas SET estado = 'reservado' WHERE vuelo_id = 101 AND estado = 'disponible';
-- Despues: Usar VACUUM configurado y monitorear versiones
-- Configurar autovacuum en postgresql.conf
ALTER TABLE reservas SET (autovacuum_vacuum_scale_factor = 0.1);
-- Consulta optimizada con limite para reducir versiones
UPDATE reservas SET estado = 'reservado'
WHERE id IN (
SELECT id FROM reservas
WHERE vuelo_id = 101 AND estado = 'disponible'
LIMIT 1
) RETURNING *;Errores comunes
- Ignorar el autovacuum: No configurar autovacuum en tablas de alta concurrencia lleva a bloat excesivo, degradando consultas. Solucion: Monitorizar pg_stat_user_tables y ajustar parametros como autovacuum_vacuum_scale_factor.
- Transacciones largas Mantener transacciones abiertas por mucho tiempo retiene versiones antiguas, bloqueando la limpieza. Evitalo con transacciones cortas y usando SAVEPOINT si es necesario.
- No usar indices adecuados En MVCC, las consultas que escanean muchas versiones son lentas. Crea indices en columnas frecuentemente filtradas (e.g., estado, vuelo_id) para acelerar snapshots.
- Confusion con niveles de aislamiento Usar el nivel por defecto (Read Committed) puede no ser suficiente para consistencia estricta. Considera Repeatable Read o Serializable para casos criticos, pero evalua el costo en concurrencia.
- Olvidar el monitoreo de dead tuples No revisar n_dead_tup en pg_stat_user_tables impide detectar problemas temprano. Implementa alertas cuando supere un umbral (e.g., 10% de las filas).
Checklist de dominio
- Explicar como MVCC permite lecturas sin bloqueos en PostgreSQL.
- Configurar autovacuum para una tabla con alta tasa de actualizaciones.
- Identificar transacciones largas usando pg_stat_activity.
- Diseñar indices que soporten consultas concurrentes frecuentes.
- Elegir el nivel de aislamiento correcto basado en requisitos de consistencia.
- Monitorear dead tuples y planificar VACUUM manual si es necesario.
- Refactorizar consultas para minimizar la creacion de versiones innecesarias.
Optimizacion de una tabla de sesiones de usuario para alta concurrencia
En este ejercicio, practicaras la aplicacion de MVCC y mantenimiento en un escenario real. Sigue estos pasos:
- Crea una tabla
user_sessionscon columnas:id(SERIAL PRIMARY KEY),user_id(INT),session_data(JSONB),last_activity(TIMESTAMP), yis_active(BOOLEAN DEFAULT true). - Simula alta concurrencia insertando 10,000 filas con datos aleatorios usando un script o multiples conexiones.
- Ejecuta transacciones concurrentes que actualicen
last_activitycada segundo para 100 sesiones aleatorias, durante 2 minutos. - Monitorea el crecimiento de dead tuples en
pg_stat_user_tablesparauser_sessions. - Configura autovacuum para la tabla con parametros agresivos (e.g.,
autovacuum_vacuum_scale_factor = 0.05). - Refactoriza una consulta tipica (e.g., actualizar sesiones inactivas) para usar un indice en
last_activityy limitar las filas procesadas. - Verifica la reduccion de bloat despues de ejecutar VACUUM ANALYZE.
Pistas
- Usa pgbench o un script en Python para simular la carga concurrente.
- Consulta la vista pg_stat_user_tables antes y despues de las actualizaciones para ver n_dead_tup.
- Considera usar un indice parcial en is_active para mejorar el rendimiento de consultas frecuentes.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.
Sigue con PostgreSQL Avanzado: Optimización para Aplicaciones de Alta Concurrencia
Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.
Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.