Concurrencia y transacciones - script
From Ibbddunq
Contents |
Intro a problemática de concurrencia
Operaciones que se ejecutan en forma concurrente
Ejemplo 1: un tablero con llaves maestras, cada una abre varias cerraduras. Yo tengo que abrir varias cerraduras, ¿qué pasa si por las dudas me llevo todo el tablero? ¿Qué pasa si otra persona tiene que abrir una cerradura para la que sirve solamente una llave que me llevé yo?
Ver que estos problemas sólo se plantean si hay operaciones concurrentes.
Preguntarles si se les ocurren otros problemas que podrían suceder, a ver que se les ocurre.
Ejemplo 2: un negocio de la era pre-informática con varios vendedores, cada cliente tiene una ficha con su límite de crédito, lo que lleva, y lo que paga, los clientes van llevando mercadería en cuenta y van haciendo pagos. También hay una ficha por cada producto, donde dice la cantidad, y se anota lo que sale por ventas (que después el cliente retirará) y lo que entra por entregas de proveedores.
Recurso
Concepto de recurso. En nuestros ejemplos está claro, los recursos son las llaves (ej 1) y las fichas (ej 2).
Ver que los problemas derivados de operaciones concurrentes están relacionados con el manejo de recursos, necesidad de garantizar el acceso exclusivo a un recurso y de liberarlo luego.
En el ej. 1 el acceso es naturalmente exclusivo, en el 2 no necesariamente, dos personas pueden mirar la misma ficha al mismo tiempo. Garantizar acceso exclusivo sería llevarme una ficha, los que quieran hacer algo con el cliente o producto tienen que esperar que yo termine. Esto podría servir si el permitir dos operaciones concurrentes sobre el mismo cliente implicara riesgo de problemas, como ya veremos.
Concepto de cola de espera: gente que está esperando por una llave (o por el acceso al tablero), o por una ficha.
Schedule
Schedule, schedules "buenos" y "malos".
Armar un schedule bueno y uno malo. Para esto creo que es mejor usar el ejemplo 2
- Los vendedores Nora y Roque están atendiendo a dos personas de la misma empresa, que es un cliente del negocio.
- El cliente tiene un límite de crédito de 100 pesos, y debe 60. O sea, puede comprar por 40.
- A Nora le piden productos por 30 pesos. Se fija en la ficha del cliente, le da el saldo. Va armando la factura.
- A Roque le piden productos por 20 pesos. Idem.
- Nora termina de despachar a la persona, vuelve al fichero, anota que el cliente debe 30 pesos más.
- Idem Roque. ¡Eh! el cliente compró por más de lo que podía, todo mal.
Acá puede venir bien anotar el schedule en castellano, pero ya con los andariveles "Nora" y "Roque" y la línea de tiempo.
Mostrar que si Roque empieza después que Nora termina, la anomalía no se produce, Roque ve que al cliente no le da el crédito, y no le vende. Todavía no vemos cómo garantizar que los schedules sean buenos, estamos reconociendo cuáles son buenos y cuáles no.
Deadlock
Si una persona necesita varios recursos, debe esperar que le lleguen todos. De acá llegar al concepto de deadlock.
Un ejemplo de deadlock de las llaves
- José se lleva la llave 1 que abre las cerraduras A y B. Se va.
- Ana se lleva la llave 2 que abre las cerraduras C y D. Se va.
- José se da cuenta que también necesita abrir la cerradura C, la \'unica llave que la abre es la que se llevó Ana. Vuelve, la llave no está, se va a tomar una cerveza sin largar la llave 1, esperando que la persona que tiene la llave 2 la devuelva.
- Ana se da cuenta que también necesita abrir la cerradura A, la \'unica llave que la abre es la que se llevó José. Vuelve, la llave no está, se va a tomar una cerveza sin largar la llave 2, esperando que la persona que tiene la llave 1 la devuelva.
Ooops cada una de las personas involucradas tiene un recurso que necesita otra. En vez de dos podrían ser más.
Ejemplo de deadlock del negocio: como vieron que la política de fijarse al principio y anotar al final tiene agujeros, hacen al revés, cuando miran una ficha de cliente o de producto se la llevan y no la devuelven hasta que terminaron. El que necesita una ficha se queda esperando que el que la tiene la devuelva. Las fichas de los productos A y B están en ficheros distintos. Tanto Roque como Nora tienen que procesar una venta que incluye a los artículos A y B, Roque empieza por el fichero del A, al mismo tiempo Ana empieza por el fichero del B. Listo. Plantear un schedule bueno: primero Roque agarra todo, después Ana agarra todo.
Diferencia entre los procesos y las personas: les es más difícil intercambiarse cosas. P.ej. Roque y Nora pueden hablar entre ellos y coordinarse, en lo que vamos a ver no se trabaja así.
En SO van a ver mucho más sobre el tema de recursos y deadlock, en IBD se ve solamente qué quiere decir, y un poquitito así de cómo evitar deadlock.
Carga
Es la medida de concurrencia de cualquier situación concurrente. P.ej. cuanto más carga, más posibilidad de espera, y a menos que lo manejemos hábilmente, mayor probabilidad de deadlock.
Concepto de transacción
en las BD y en la vida
Ejemplos de la vida: pago con tarjeta, intercambio de rehenes.
Ejemplos de BD: si voy a cargar una factura (vg ej de productos clientes y facturas (1) guía SQL avanzado), tengo que cargar los ítems. Si en una BD de una biblioteca (ej. Biblioteca (4) guía SQL avanzado) una persona en el mismo acto se lleva dos libros y devuelve tres, eso hay que registrarlo transaccionalmente. Entender qué quiere decir "transaccionalmente".
Hablar de interacción entre un SI y una BD.
propiedades ACID
- Atomicidad: la garantiza el motor. Las aplicaciones deben la responsabilidad de demarcar transacciones (ya veremos qué es eso).
- Consistencia: la debe garantizar uno (el que envía las sentencias SQL al motor) haciendo operaciones correctas en cada transacción. Las cuestiones de consistencia más semántica no pueden resolverse mediante restricciones, hay que hacer las cosas bien. P.ej.
- si tengo un sistema de stock en distintos depósitos y muevo mercadería de uno a otro, tengo que hacer dos operaciones, si hago una sola está mal.
- si agrego una factura por un importe, debo agregar ítems que justifiquen ese importe.
- Durabilidad: la garantiza el motor.
- Aislamiento: necesita un tratamiento particular, de eso vamos a hablar bastante.
demarcación
Contar la idea de demarcación, se puede hacer pensando desde el motor, me llegan sentencias SQL de un usuario, cómo sé cuándo termina una transaccion y empieza otra. P.ej. en el sistema de la biblioteca, un usuario se lleva dos libros, después otro se lleva tres y devuelve uno, después se agrega un nuevo socio que retira un libro, etc.
costo de la serialización
Costo del aislamiento si lo llevo a serialización, necesidad de manejarlo a mano.
Pensar en el sistema de carga on-line de declaraciones de Ganancias de la AFIP el día que se vence. Ahí es muy difícil que tengas problemas de concurrencia, porque mi declaración no se pisa con la tuya. Entonces la serialización no trae ventajas y sí hace impracticable a un sistema con una BD relacional atrás.
Referencia: pág 573 Silberschatz
Tx en una BD, concretamente
¿De dónde le llegan a una BD las transacciones que tiene que procesar?
- De programas externos que le demarcan transacciones, o sea, le dicen "acá empieza transacción", después sentencias (en nuestro caso en SQL), después "acá termina transacción"
- De ejecutar stored procedures.
¿Cuáles son los recursos? Los objetos a nivel instancia, nosotros nos vamos a manejar pensando en filas (también se podría trabajar usando las tablas como recursos, pero es más raro). En un rato vamos a ver qué quiere decir tener acceso a una fila.
¿Cuáles son las operaciones? Select, insert, update, delete.
Entonces en nuestro análisis de tx concurrentes, vamos a tener un andarivel para cada tx, y lo que vamos a anotar son operaciones de (instancia de) BD.
Como se nos complica tener programas externos que se comuniquen con la BD, y también ejecutar stored procedures paso por paso, vamos a simular este comportamiento simulando a mano en el Query Browser la ejecución de las tx, incluyendo comienzo y fin.
Anomalías de concurrencia - y un ejemplo ya en el dominio de las BD
(acá borramos todo el pizarrón, salvo tal vez una listita con palabras: recurso / deadlock / tx. Necesitamos lugar para escribir los dos stored procedures, y que nos quede un cacho libre. OJO que los pizarrones no son muy grandes)
Se llama anomalía de concurrencia a cualquier situación en la que se produce un error relacionado con la ejecución concurrente de transacciones en una BD, que no ocurriría si se ejecutaran primero una y después la otra (o sea, en forma serializada)
Las dos manifestaciones más comunes de anomalías son:
- o bien se permite hacer una operación que no debería hacerse. P.ej. cuando un cliente en el negocio compró por más de lo que podía.
- o bien en la base quedan datos erróneos. Ejemplo: en el negocio cada vendedor al principio cuando se fija el disponible del cliente lo anota, hace la cuenta para obtener el nuevo disponible, y cuando termina borra el número que había y pone el suyo. Si en el medio otra persona actualizó el crédito disponible, fuimos.
En este punto se puede pasar al sp agregarEncomienda
, ver schedules buenos y malos. De esta parte debería
- mostrarse que los schedules "buenos" son los que dan el mismo resultado de uno serial, y los "malos" son los que no. Prepárense uno bueno pero no serial, y otro malo, o varios.
- con qué tiene que ver la posibilidad de anomalías: con las operaciones (p.ej. si son todos select no pasa nada) y muy importante, con los datos involucrados. Ningún schedule de agregado simultáneo de dos encomiendas en dos servicios distintos es malo.
si ven que cambiando el ejemplo esto se muestra mejor, escucho propuestas.
Finalmente contar que no vamos a corregir los schedules "malos" para que se porten bien, sino que vamos a evitar que pasen. O sea, vamos a agregar cosas para que sólo puedan ocurrir los schedules "buenos" y evitar la posibilidad de que dos tx concurrentes corran con un schedule "malo".
Cómo demarcamos transacciones
start transaction - commit - rollback.
se puede ver con el ejemplo del stored procedure pasarPeso.
¿y si hago un start pero después no cierro ni por commit ni por rollback? ¡¡está todo mal!!
Lockeos
Ya vimos que los recursos en los que vamos a pensar son las filas.
Un lockeo es una declaración que hace una transacción, en la que le pide a la BD que limite lo que pueden hacer otras tx que se están ejecutando en forma concurrente con una o varias filas.
Hay dos tipos de lockeo: compartido y exclusivo.
- en el compartido, sí se permite que otras tx puedan leer, pero no se permite que otras tx puedan escribir ... ni poner lock exclusivo (ya veremos esto).
- en el exclusivo ni escribir, ni poner lock compartido, ni poner lock exclusivo.
Qué operaciones de BD generan lockeos
SELECT ... LOCK IN SHARE MODE (lock compartido) SELECT ... FOR UPDATE (lock exclusivo) UPDATE (lock exclusivo)
Qué operaciones de BD liberan filas lockeadas
COMMIT ROLLBACK
¿Y si una tx T1 quiere hacer una operación que no se puede porque otra tx T2 puso lock? T1 debe esperar que T2 termine.
Acá hacer ejemplo de tx concurrentes, probar qué pasa si a tal SELECT le agrego una de las dos formas de lockeo si el otro quiere hacer SELECT / UPDATE, cuándo se para, cuándo se libera. Bien fácil, escribir un
START TRANSACTION SELECT f1 UPDATE f1 SELECT f2 COMMIT (o ROLLBACK)
y un
START TRANSACTION SELECT f2 UPDATE f1 SELECT f1 COMMIT (o ROLLBACK)
plantear dos ejecuciones concurrentes. Repasar la diferencia entre COMMIT y ROLLBACK. Y preguntar qué pasa si las dos tx trabajan sobre distintas filas. Se puede jugar haciendo que el UPDATE sea sobre el mismo o sobre distinto atributo. Jugar siempre con las operaciones sobre f1.
Después de esto sí le ponemos lockeo a las operaciones de f2, para que salte un deadlock.
Acá también se puede ver qué pasa si la primera hace un SELECT f1 LOCK IN SHARE MODE y después un UPDATE f1: upgrade de lock.
Uso de lockeos para resolver anomalías de concurrencia
Ver en el ejemplito de recién que la existencia de lock provoca que ciertos schedules no sean posibles. Ese va a ser el truco.
pasarPeso
- ver dónde está el problema, cuál es la condición de "mal schedule": 2do select antes del 1er update.
- ¿cómo lo solucionamos con lockeos? ¿alcanza compartido, o hace falta exclusivo?
agregarEncomienda
... donde ya volamos el SELECT del servicio
- ver condición de "mal schedule".
- pensar cuál es el recurso que conviene lockear ... la fila de servicio, cuyo SELECT en el estado actual del sp no necesitamos.
Moraleja: OJO que a veces el recurso a reservar = la fila a lockear, no es ninguna de las que ya estamos trabajando.
- ¿cómo lo solucionamos con lockeos?