Mélanger Active Record et mini_sql entraîne un comportement inattendu

En examinant certains journaux SQL, j’ai remarqué que certaines requêtes ne sont pas cohérentes avec l’intention du code en raison d’un mélange entre l’utilisation d’Active Record et mini_sql.

Lors de la mise à jour de certains éléments révisables, nous incrémentons la version au sein d’une transaction pour éviter d’éventuelles conditions de course (comme le montre l’extrait de code ci-dessous). Bien qu’il semble que l’incrémentation fasse partie de la transaction, ce n’est pas le cas.

Reviewable.transaction est ici une fonctionnalité d’Active Record, tandis que increment_version! utilise mini_sql :

Active Record n’est pas au courant des opérations effectuées par mini_sql. Il semble qu’Active Record utilise une fonctionnalité de type « paresseux », où le BEGIN est émis juste avant l’exécution de la première requête dans la transaction. Ainsi, la version est incrémentée en premier, puis la transaction commence juste avant l’exécution de la première requête d’Active Record. Cela donne quelque chose comme ceci :

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

Avec l’incrémentation de la version en dehors de la transaction, certaines garanties offertes par le verrouillage optimiste ne sont pas respectées, car l’incrémentation n’est pas atomique par rapport à la transaction.

4 « J'aime »

Intéressant, nous devrions enseigner le mini SQL à AR, cela vaut certainement la peine d’être corrigé

3 « J'aime »