Mezclar Active Record y mini_sql genera un comportamiento inesperado

Al revisar algunos registros SQL, noté que algunas consultas no son coherentes con lo que el código pretende hacer debido al uso combinado de Active Record y mini_sql.

Al intentar actualizar algunos elementos revisables, incrementamos la versión dentro de una transacción para evitar posibles condiciones de carrera (como muestra el fragmento de código a continuación). Aunque parece que el incremento forma parte de la transacción, en realidad no lo es.

Reviewable.transaction aquí es una característica de Active Record, mientras que increment_version! utiliza mini_sql:

Active Record no es consciente de lo que hace mini_sql. Parece que Active Record utiliza alguna característica de ejecución diferida, donde el BEGIN se emite justo antes de ejecutar la primera consulta dentro de la transacción. Así, la versión se incrementa primero y luego comienza la transacción justo antes de que se ejecute la primera consulta de Active Record. Se convierte en algo así:

UPDATE reviewables SET version = version + 1 WHERE version=version AND id = reviewable.id RETURNING version;
BEGIN;
...

Con el incremento de la versión fuera de la transacción, no se logran algunas garantías proporcionadas por el bloqueo optimista. Esto se debe a que el incremento no es atómico con la transacción.

4 Me gusta

Interesante, deberíamos enseñar mini SQL a informar a AR, definitivamente vale la pena solucionarlo

3 Me gusta