Mittwoch, April 16, 2014

Read Committed Isolation Level im SQL Server

Im SQLPerformance.com Blog hat Paul White einige interessante Punkte zur Implementierung des Isolation Levels Read Committed im SQL Server aufgeschrieben. Grundsätzlich gibt es im SQL Server dieser Tage zwei Implementierungen für Read Committed, von denen die ältere (zumindest vom Herrn White) als Locking Read Committed bezeichnet wird. Da der Autor einen weiteren Artikel zum Thema ankündigt, starte ich an dieser Stelle eine Aufzählung:
  • The Read Committed Isolation Level: die traditionelle Implementierung des Isolation Levels Read Committed ist im SQL Server aktiv, wenn der Parameter READ_COMMITTED_SNAPSHOT auf OFF gesetzt ist. Sie hält ein möglichst kurzes shared lock auf gelesene rows und pages, das nach der Leseoperation sofort wieder frei gegeben wird (und konkurrierende Transaktionen kurzfristig aussperrt, weil diese zur Datenänderung ein exklusives Lock benötigen würden). Das Verfahren entspricht wohl den Anforderungen des SQL Standards (sagt jedenfalls der Herr White, wobei er allerdings nicht genau bestimmt, von welchem Standard er spricht), bringt aber ein paar sehr bizarre Effekte mit sich. Ein Statement:
    • kann die selbe Zeile mehrfach lesen (wenn sie durch eine konkurrierende Änderung ihre Position im Index bzw. in der Tabelle ändert).
    • kann eine Zeile komplett verpassen.
    • liefert keine konsistente point-in-time-Sicht der Daten: das Ergebnis einer Query kann also ein Zustand sein, den es in dieser Form in den Daten nie gegeben hat.
  • Read Committed Snapshot Isolation: erläutert das Verhalten bei Verwendung von RCSI (also Read Committed Snapshot Isolation). Hier werden konsistente Daten für den Startzeitpunkt der Query gelesen - das Verhalten ist also jenes, das man von Oracles Implementierung von Read Committed her kennt. Der Herr White erläutert relativ ausgiebig die Fälle, in denen dieses Verhalten nicht das gewünschte sein könnte:
    • "RCSI is typically not a good choice for any T-SQL code whose correctness depends on blocking if a concurrent uncommitted change exists." Nun ja, dieser Fall scheint mir halbwegs in den Bereich von dirty read zu reichen.
    • "RCSI might also not be the right choice if the code depends on reading current committed data, rather than the latest committed data as at the time the statement started." Für lang laufende Queries könnte das tatsächlich ein potentielles Problem sein - allerdings halte ich die Standard-Implementierung des SQL Servers nicht für eine sinnvolle Lösung dazu.
    • Details zur technischen Implementierung und den erforderlichen Locks liefert der Folge-Artikel Data Modifications under Read Committed Snapshot Isolation.
    • Weitere Informationen zu möglichen Effekten und Fehlern liefert The SNAPSHOT Isolation Level. Interessant sind dabei einerseits die spezifischen Unterschiede der Implementierung zum Ansatz von Oracle (etwa die Fehlermeldungen beim konkurrierenden Update oder beim Truncate) und andererseits die offensichtlich erforderlichen Verhaltenserklärungen für Aspekte, die dem Oracle-User selbstverständlich erscheinen (Stichwort: Write Skew). Manchmal ist es ganz nützlich, sich klar zu machen, dass Selbstverständlichkeiten von Standpunkt und Perspektive abhängen...
Der Autor präsentiert diese Informationen eher wertneutral ("We also have to bear in mind that many production queries only really need an approximate or best-effort answer to some types of question anyway. The fact that some rows are missing or double-counted might not matter much in the broader scheme of things."), aber ich erinnere mich noch daran, wie ungläubig ich reagiert habe, als ich erstmals mit diesem Verhalten konfrontiert wurde. Meiner Meinung nach ist diese Implementierung von Read Committed in einem OLTP System nahezu unbrauchbar (und ein sehr starkes Argument für Oracles Lesekonsistenzmechanismen). Aber inzwischen gibt es ja die Snapshot-Alternative, die Paul White in einem Folgeartikel erläutern will, den ich dann hier ergänzen werde (wenn ich es nicht vergesse).

Keine Kommentare:

Kommentar veröffentlichen