Mysql: Manejo de Concurrencia con Lock Tables

Mysql: Manejo de Concurrencia con Lock Tables

Hay ocasiones en las que se necesita que una pieza de código pueda ser ejecutada simultáneamente sin distorsionar sus resultados, y hay código que no cumple con esta condición a menos que tomemos cuidados especiales.

Por ejemplo, supongamos un sistema de turnos donde cada turno debe tener un consecutivo único y se pueden hacer solicitudes desde más de un punto. Para esto nos valemos de un contador que está en una tabla de una base de datos MySQL, entonces podríamos usar queries como los siguientes:

  • UPDATE tbl_contador SET valor = valor + 1; //incrementar el contador
  • SELECT valor FROM contador; //retornar el contador asignado

¿Pero qué pasaría si dos o más usuarios solicitan turnos al mismo tiempo? Es posible que sus consultas se entrelacen entregando a dos o más usuarios el mismo número, por ejemplo supongamos que el contador inicia en 0, las solicitudes pueden llegar a la base de datos en este orden:

  • UPDATE tbl_contador SET valor = valor + 1; //pasa a 1
  • UPDATE tbl_contador SET valor = valor + 1; //pasa a 2
  • SELECT valor FROM contador; //retorna 2
  • SELECT valor FROM contador; //retorna 2

¿Qué podemos hacer?

Hay varios queries que pueden hacer esta operación, pero sin falta todos sufrirán del mismo problema, la realidad es que este código no es seguro para ser ejecutado en paralelo, así que lo que queremos es precisamente evitar este paralelismo, y en caso de que lleguen 2 o más peticiones, se necesita que se forme una lista de espera dónde se ejecuten una a una.

Pero no hay por qué preocuparse ya que no tenemos que programar esta lista de espera por nuestra cuenta, afortunadamente tenemos a nuestra disposición el comando LOCK TABLES WRITE, que permite que cada sesión reserve una lista de tablas que no desea que sean manipuladas por otra sesión, si una tabla ha sido bloqueada y otra sesión la solicita, tendrá que esperar a que se finalice el bloqueo y mientras tanto quedará en una lista de espera gestionada automáticamente por MySQL, de modo que lo único que tendremos que hacer es adicionar dos instrucciones, así:

  • LOCK TABLES tbl_contador WRITE;
  • UPDATE tbl_contador SET valor = valor + 1; //incrementar el contador
  • SELECT valor FROM contador; //retornar el contador asignado
  • UNLOCK TABLES;

WRITE al final de LOCK TABLES hace que sólo la sesión que solicitó el bloqueo pueda leer o escribir en las tablas bloqueadas, hay otros tipos de bloqueo, como LOCK TABLES READ, que son últiles en otras circunstancias.En todo caso las tablas que se van a usar luego de LOCK TABLES deben haber sido bloqueadas primero, incluso con el mismo alias.

El último comando, UNLOCK TABLES, libera todas las tablas bloqueadas por la sesión actual, es aconsejable que el tiempo que trascurre desde que se bloquean las tablas hasta que se liberan sea el menor posible y también se recomienda llamar a este comando explícitamente, tan pronto como se termina de usar las tablas que estaban bloqueadas.

Si te gustó este artículo seguro hay otros en este Blog que te pueden interesar, no olvides suscribirte, darle me gusta y compartir.

Deja un Comentario

CAPTCHA code
X