Dos cajeros, una cuenta
Cada transacción, sola, hace bien su trabajo. Juntas, al mismo tiempo, pueden perder un depósito. Al terminar podrás provocar y reconocer los tres problemas clásicos.
Primero, la idea completa
Mira el video entero o salta a la parte que quieras repasar. Después, cada idea tiene su propia escena para tocarla.
Muchas transacciones, los mismos datos
Una base de datos real atiende a cientos de usuarios a la vez: cajeros, la tienda en línea, un reporte que corre de noche. Esa concurrencia es necesaria; si cada transacción tuviera que esperar a que terminara la anterior, todo sería lentísimo.
El riesgo: dos transacciones que, cada una por sí sola, son correctas, pueden producir un resultado incorrecto cuando se intercalan. Hay tres formas clásicas en que esto pasa.
02 · Actualización perdidaUno escribe encima del otro
Ana tiene Q100. El cajero A va a depositar Q50 y el cajero B, Q30:
- t1: A lee el saldo: 100.
- t2: B lee el saldo: también 100.
- t3: A escribe 100 + 50 = 150.
- t4: B escribe 100 + 30 = 130, calculado con lo que leyó en t2.
B sobrescribió el cambio de A sin siquiera mirarlo. El depósito de A se perdió: Ana debería tener Q180 y tiene Q130.
Cambia el orden en que se ejecutan los cuatro pasos y mira el saldo final. ¿Qué órdenes pierden un depósito?
Leer algo que nunca existió
Ocurre cuando una transacción lee, o peor, actualiza, un dato que otra transacción cambió pero todavía no confirmó. Si esa otra transacción termina con ROLLBACK, la primera trabajó con un valor que ya no existe y, en cierto sentido, nunca existió.
Ejemplo: A resta Q60 a Ana sin confirmar; B lee 40 y le niega un préstamo por “saldo bajo”; A hace ROLLBACK. Ana siempre tuvo Q100, pero B ya tomó una decisión equivocada. También se le llama lectura sucia.
Sumar mientras el dinero se mueve
A está sumando los saldos de tres cuentas, una por una. A la mitad, B transfiere Q10 de la cuenta 3 a la cuenta 1 y confirma. A ya había leído la cuenta 1 (sin los 10) y ahora lee la cuenta 3 (sin los 10). Su total sale Q10 corto, aunque no se perdió ni un centavo.
Fíjate en la diferencia con el caso anterior: aquí A nunca vio nada sin confirmar. B confirmó todo antes de que A leyera la cuenta 3. Aun así, A vio un estado de la base de datos que nunca existió completo.
Mueve el momento en que B hace la transferencia y observa lo que suma A.
Controlar la concurrencia
Cuando varias transacciones se ejecutan a la vez, la propiedad de aislamiento puede romperse. Por eso el sistema controla cómo interactúan, con un esquema de control de concurrencia. El más usado son los bloqueos, el tema de la siguiente lección.
Mientras tanto, hay un truco sencillo contra la actualización perdida: no calcules el nuevo valor en tu programa con algo que leíste antes. Pide a la base de datos que lo calcule con el valor del momento:
UPDATE cuentas SET saldo = saldo + 50 WHERE id = 1
Así, si otra transacción cambió el saldo, la tuya espera a que termine y suma sobre el valor ya actualizado.
06 · PrediceAntes de leer la respuesta
Para ver una lectura sucia, la sesión que lee debe estar en
READ UNCOMMITTED. Cámbialo en el selector de la sesión antes de su BEGIN.Tu turno: dos sesiones sobre las mismas cuentas
Dos sesiones, como dos cajeros, sobre las mismas tres cuentas: Ana tiene Q100, Beto Q50 y Carla Q80, en total Q230. Ambas empiezan en READ COMMITTED. Tu trabajo es provocar a propósito los tres problemas y luego evitar el primero. Alterna entre las dos sesiones: el orden es lo que importa.
Comprueba lo que entendiste
Cada respuesta incorrecta explica por qué parece correcta y en qué falla.