Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Warum ignoriert Rails ein Rollback in einer (pseudo-)verschachtelten Transaktion?

Genau so funktionieren verschachtelte Transaktionen wurde für konzipiert. Ich zitiere aus Oracle-Dokumenten:

Also eine untergeordnete Transaktion in einer regulären verschachtelten Transaktion hat kein Mitspracherecht darüber, wie er oder die anderen Kinder oder Eltern (größere Transaktion ) sich verhalten könnte, außer gegenseitige Daten zu ändern oder bei einer Ausnahme fehlzuschlagen.

Aber Sie können ihm (untergeordnete Transaktion) gewähren ) eine sehr begrenzte Möglichkeit, über sein Schicksal abzustimmen, indem er die sub-transaction nutzt wie in den docs von Rails beschrieben indem Sie requires_new: true übergeben

User.transaction do
  User.create(username: 'Kotori')
  User.transaction(requires_new: true) do
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback
  end
end

Was, wie die Dokumente sagen, nur 'Kotori' erstellt. da das mächtige 'Nemu'-Kind sich entschieden hat, still zu sterben.

Weitere Details zu Verschachtelten Transaktionsregeln (Oracle-Dokumentation )

Aktualisierung:

Um besser zu verstehen, warum nested transactions gerailt werden auf diese Weise funktioniert, müssen Sie etwas mehr darüber wissen, wie verschachtelte Transaktionen auf DB-Ebene funktionieren, ich zitiere aus rails-API-Dokumentation :

Ok, dann beschreibt die Dokumentation das Verhalten einer nested transaction in den beiden genannten Fällen wie folgt:

Im Falle eines verschachtelten Aufrufs #transaction verhält sich wie folgt:

  • Der Block wird ausgeführt, ohne etwas zu tun. Alle Datenbankanweisungen, die innerhalb des Blocks vorkommen, werden effektiv an die bereits geöffnete Datenbanktransaktion angehängt.

  • Wenn jedoch :requires_new gesetzt ist, wird der Block in einen Datenbanksicherungspunkt eingeschlossen, der als Untertransaktion fungiert.

Ich stelle mir vorsichtig vor, stelle mir nur vor das:

Option(1) (ohne require_new) ist vorhanden, falls Sie ein DBMS verwendet haben, das nested transactions vollständig unterstützt oder Sie sind mit dem "falschen" Verhalten von nested_attributes zufrieden

während option(2) soll den savepoint unterstützen Problemumgehung, wenn Sie dies nicht tun.