Mischen von Active Record und mini_sql führt zu unerwartetem Verhalten

Beim Durchsuchen einiger SQL-Protokolle habe ich festgestellt, dass einige Abfragen nicht mit den beabsichtigten Codezielen übereinstimmen, da Active Record und mini_sql inkonsistent miteinander verwendet werden.

Beim Versuch, einige Reviewables zu aktualisieren, erhöhen wir die Versionsnummer innerhalb einer Transaktion, um mögliche Race Conditions zu verhindern (wie der folgende Code-Ausschnitt zeigt). Obwohl der Inkrementierungsschritt Teil der Transaktion zu sein scheint, ist er es in Wirklichkeit nicht.

Reviewable.transaction ist hier eine Active-Record-Funktion, während increment_version! mini_sql verwendet:

Active Record ist sich nicht bewusst, was mini_sql tut. Es scheint, dass Active Record eine Art Lazy-Feature verwendet, bei dem BEGIN erst kurz vor der Ausführung der ersten Abfrage innerhalb der Transaktion ausgegeben wird. Die Versionsnummer wird also zuerst erhöht, und erst dann beginnt die Transaktion, kurz bevor die erste Abfrage von Active Record ausgeführt wird. Das Ergebnis sieht dann etwa so aus:

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

Da die Versionsinkrementierung außerhalb der Transaktion stattfindet, können einige Garantien des optimistischen Lockings nicht eingehalten werden, da die Inkrementierung nicht atomar mit der Transaktion ist.

4 „Gefällt mir“

Interessant, wir sollten Mini SQL an AR weitergeben, das ist definitiv eine Korrektur wert.

3 „Gefällt mir“