Suche…


Bemerkungen

Transaktionen sind Schutzblöcke, bei denen SQL-Anweisungen nur dauerhaft sind, wenn sie alle als eine einzige Aktion erfolgreich sein können. Das klassische Beispiel ist eine Überweisung zwischen zwei Konten, bei denen Sie nur dann eine Einzahlung vornehmen können, wenn die Auszahlung erfolgreich war, und umgekehrt. Transaktionen erzwingen die Integrität der Datenbank und schützen die Daten vor Programmfehlern oder Datenbankausfällen. Sie sollten also grundsätzlich Transaktionsblöcke verwenden, wenn Sie mehrere Anweisungen haben, die zusammen oder nicht ausgeführt werden müssen.

Grundlegendes Beispiel

Zum Beispiel:

ActiveRecord::Base.transaction do
  david.withdrawal(100)
  mary.deposit(100)
end

Dieses Beispiel nimmt nur Geld von David und gibt es an Mary, wenn weder Abhebung noch Einzahlung eine Ausnahme darstellen. Ausnahmen erzwingen einen ROLLBACK, der die Datenbank vor dem Beginn der Transaktion in den Status zurücksetzt. Beachten Sie jedoch, dass die Instanzdaten der Objekte nicht in den Zustand vor der Transaktion zurückversetzt werden.

Verschiedene ActiveRecord-Klassen in einer einzelnen Transaktion

Obwohl die Transaktionsklassenmethode für einige ActiveRecord-Klasse aufgerufen wird, müssen die Objekte im Transaktionsblock nicht alle Instanzen dieser Klasse sein. Dies liegt daran, dass Transaktionen pro Datenbankverbindung und nicht pro Modell erfolgen.

In diesem Beispiel wird ein Saldasatz transaktional gespeichert, obwohl die Transaktion für die Konto-Klasse aufgerufen wird:

Account.transaction do
  balance.save!
  account.save!
end

Die Transaktionsmethode ist auch als Modellinstanzmethode verfügbar. Sie können beispielsweise auch Folgendes tun:

balance.transaction do
  balance.save!
  account.save!
end

Mehrere Datenbankverbindungen

Eine Transaktion wirkt auf eine einzelne Datenbankverbindung. Wenn Sie über mehrere klassenspezifische Datenbanken verfügen, schützt die Transaktion die Interaktion zwischen ihnen nicht. Eine Problemumgehung besteht darin, eine Transaktion für jede Klasse zu beginnen, deren Modelle Sie ändern:

Student.transaction do
  Course.transaction do
    course.enroll(student)
    student.units += course.units
  end
end

Dies ist eine schlechte Lösung, aber vollständig verteilte Transaktionen liegen nicht im Bereich von ActiveRecord.

Speichern und Zerstören werden automatisch in eine Transaktion eingeschlossen

Sowohl #save als auch #destroy werden in einer Transaktion verpackt, die sicherstellt, dass das, was Sie bei Validierungen oder Rückrufen tun, unter ihrer geschützten Abdeckung geschieht. Sie können Validierungen verwenden, um nach Werten zu after_* , von denen die Transaktion abhängig ist, oder Sie können Ausnahmen in den Rückrufen für das Rollback after_* , einschließlich after_* .

Folglich werden Änderungen an der Datenbank nicht außerhalb Ihrer Verbindung sichtbar, bis der Vorgang abgeschlossen ist. Wenn Sie beispielsweise versuchen, den Index einer Suchmaschine in after_save aktualisieren, wird der aktualisierte Datensatz nicht after_save . Der after_commit Callback ist der einzige, der ausgelöst wird, wenn die Aktualisierung festgeschrieben ist.

Rückrufe

Es gibt zwei Arten von Rückrufen, die mit dem after_commit und after_rollback Transaktionen verbunden sind: after_commit und after_rollback .

after_commit Rückrufe werden für jeden Datensatz, der innerhalb einer Transaktion gespeichert oder zerstört wurde, unmittelbar nach dem after_commit der Transaktion aufgerufen. after_rollback Rückrufe werden für jeden Datensatz, der innerhalb einer Transaktion gespeichert oder zerstört wurde, unmittelbar nach dem after_rollback der Transaktion oder des Sicherungspunkts aufgerufen.

Diese Callbacks sind hilfreich für die Interaktion mit anderen Systemen, da Ihnen garantiert wird, dass der Callback nur ausgeführt wird, wenn sich die Datenbank in einem permanenten Zustand befindet. after_commit ist beispielsweise ein guter Ort, um einen Cache zu after_commit da das Löschen innerhalb einer Transaktion dazu führen könnte, dass der Cache vor der Aktualisierung der Datenbank erneut generiert wird.

Transaktion rückgängig machen

ActiveRecord::Base.transaction verwendet die Ausnahme ActiveRecord::Base.transaction ActiveRecord::Rollback , um ein absichtliches Rollback von anderen Ausnahmesituationen zu unterscheiden. Normalerweise führt das .transaction einer Ausnahme dazu, dass die .transaction Methode die Datenbanktransaktion .transaction und die Ausnahme .transaction . Wenn Sie jedoch eine ActiveRecord::Rollback Ausnahme ActiveRecord::Rollback , wird die Datenbanktransaktion zurückgesetzt, ohne die Ausnahme zu übergeben.

Zum Beispiel könnten Sie dies in Ihrem Controller tun, um eine Transaktion rückgängig zu machen:

class BooksController < ActionController::Base
  def create
    Book.transaction do
      book = Book.new(params[:book])
      book.save!
      if today_is_friday?
        # The system must fail on Friday so that our support department
        # won't be out of job. We silently rollback this transaction
        # without telling the user.
        raise ActiveRecord::Rollback, "Call tech support!"
      end
    end
    # ActiveRecord::Rollback is the only exception that won't be passed on
    # by ActiveRecord::Base.transaction, so this line will still be reached
    # even on Friday.
    redirect_to root_url
  end
end


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow