Anomalías de concurrencia13 temas

Anomalías de concurrencia

Qué pasa cuando la concurrencia queda sin control

Las bases de datos ejecutan varias transacciones a la vez, pero cuando varias manipulan los mismos datos al mismo tiempo, pueden producirse errores o anomalías.


Las cuatro anomalías de concurrencia

Lectura sucia (dirty read)

Una transacción T1 escribe un cambio. Otra transacción T2 lee ese cambio antes de que T1 haga commit. T1 hace rollback. T2 leyó datos que nunca existieron: trabajó con información basada en una transacción que se deshizo.

Diagrama: lectura sucia — T2 lee un cambio no confirmado de T1

No hay separación entre datos confirmados y datos en progreso. Una transacción ve todo lo que otras escriben, incluso si todavía no está confirmado.

Lectura no repetible (non-repeatable read)

Una transacción lee una fila. Otra transacción modifica esa misma fila y hace commit. La primera transacción lee la misma fila otra vez y obtiene un valor distinto.

Diagrama: lectura no repetible — el valor de una fila cambia entre dos lecturas

El aislamiento permite que escrituras confirmadas de otras transacciones modifiquen datos que ya fueron leídos, sin que la transacción en curso lo sepa.

Lectura fantasma (phantom read)

Una transacción ejecuta una consulta con una condición (por ejemplo, filas donde precio > 100). Otra transacción inserta una fila que también cumple esa condición y hace commit. La primera transacción ejecuta la misma consulta otra vez y aparece una fila nueva que antes no estaba.

Diagrama: lectura fantasma — aparece una fila nueva que cumple la condición

El aislamiento bloquea filas existentes pero no impide que aparezcan filas nuevas que coincidan con la condición.

Actualización perdida (lost update)

Dos transacciones leen el mismo valor. Ambas lo modifican en base a lo que leyeron. Ambas escriben el resultado. La segunda escritura sobrescribe a la primera y su cambio se pierde. No hay datos inválidos, solo incorrectos.

Diagrama: actualización perdida — dos transacciones sobrescriben la escritura de la otra

Anomalía Qué permite Por qué es peligrosa
Lectura sucia T2 lee datos no confirmados de T1 Trabaja con información que puede desaparecer
Lectura no repetible T2 modifica datos que T1 ya leyó T1 obtiene resultados inconsistentes
Lectura fantasma T2 inserta filas que coinciden con la consulta de T1 T1 ve resultados incompletos o inconsistentes
Actualización perdida T2 sobrescribe la escritura de T1 Los datos quedan consistentes pero incorrectos

Cada anomalía en acción con SQL

Las siguientes simulaciones asumen una sesión por transacción.

Lectura sucia

-- Sesión 1                      |  -- Sesión 2
BEGIN;                           |
UPDATE cuentas SET saldo=200     |
  WHERE id='A';                  |
                                 |  BEGIN;
                                 |  SELECT saldo FROM cuentas
                                 |    WHERE id='A';
                                 |  -- lee 200 (no confirmado)
ROLLBACK;                        |
-- saldo de A vuelve a 500       |
                                 |  -- Sesión 2 trabajó con 200
                                 |  -- que nunca existió realmente

Lectura no repetible

-- Sesión 1                      |  -- Sesión 2
BEGIN;                           |
SELECT saldo FROM cuentas        |
  WHERE id='A';                  |
-- lee 500                       |
                                 |  BEGIN;
                                 |  UPDATE cuentas SET saldo=700
                                 |    WHERE id='A';
                                 |  COMMIT;
SELECT saldo FROM cuentas        |
  WHERE id='A';                  |
-- lee 700 (DISTINTO)            |
-- misma consulta, mismo id,     |
-- mismo resultado? NO           |
COMMIT;                          |

Lectura fantasma

-- Sesión 1                      |  -- Sesión 2
BEGIN;                           |
SELECT * FROM productos          |
  WHERE precio > 100;            |
-- devuelve 2 filas              |
                                 |  BEGIN;
                                 |  INSERT INTO productos
                                 |    (id, precio) VALUES (3, 150);
                                 |  COMMIT;
SELECT * FROM productos          |
  WHERE precio > 100;            |
-- devuelve 3 filas (¡una más!)  |
-- apareció un fantasma          |
COMMIT;                          |

Actualización perdida

-- Sesión 1                      |  -- Sesión 2
BEGIN;                           |
SELECT stock FROM productos      |
  WHERE id=1;                    |
-- lee 10                        |
                                 |  BEGIN;
                                 |  SELECT stock FROM productos
                                 |    WHERE id=1;
                                 |  -- lee 10
UPDATE productos SET stock=11    |
  WHERE id=1;                    |
-- escribe 11                    |
                                 |  UPDATE productos SET stock=11
                                 |    WHERE id=1;
                                 |  -- escribe 11 (basado en 10)
COMMIT;                          |
                                 |  COMMIT;
-- stock final: 11               |
-- debería ser: 12               |
-- se perdió una actualización   |

Malentendidos comunes sobre las anomalías

Error: Las lecturas sucias solo pasan cuando una transacción se cae.

Una lectura sucia ocurre cuando T2 lee datos de T1 y T1 hace rollback. No importa si T1 se cayó o decidió deshacer el cambio manualmente. El problema es leer datos que no están confirmados, independientemente de la causa del rollback.


Error: Lectura no repetible y fantasma son lo mismo.

No. En la lectura no repetible cambia el valor de una fila existente. En el fantasma aparece una fila nueva que cumple la condición. Una modifica datos, la otra modifica el conjunto de resultados.


Error: Las actualizaciones perdidas solo pasan si usamos Read Uncommitted.

Falso. La actualización perdida puede ocurrir incluso en Read Committed si el programa lee el valor, lo modifica en la aplicación y luego escribe. Dos instancias del mismo programa pueden leer el mismo valor, modificarlo y sobrescribirse mutuamente sin que el motor lo detecte.

Autoevaluación: Anomalías de Concurrencia

1/3