Fragenzusammenfassung
Dies ist eine Frage zur Serialisierbarkeit von Abfragen innerhalb einer SQL-Transaktion.Transaktionsisolation über mehrere Tabellen mit PostgreSQL MVCC
Insbesondere verwende ich PostgreSQL. Es kann davon ausgegangen werden, dass ich die aktuellste Version von PostgreSQL verwende. Von dem, was ich gelesen habe, glaube ich, dass die Technologie, die verwendet wird, um zu unterstützen, was ich versuche, als "MultiVersion Concurrency Control" oder "MVCC" bekannt ist.
Um es zusammenzufassen: Wenn ich eine primäre Tabelle und mehr als 1 mit Fremdschlüsseln verknüpfte Tabelle mit dieser primären Tabelle verbunden haben, wie garantiere ich, dass für einen bestimmten Schlüssel in den Tabellen und alle Anzahl von SELECT-Anweisungen, die diesen Schlüssel innerhalb einer Transaktion verwenden, von denen jede SELECT von einer der verknüpften Tabellen ist, erhalte ich Daten, wie sie zu dem Zeitpunkt existierten, als ich die Transaktion startete?
Andere Fragen
Diese Frage ist ähnlich, aber breiter, und die Frage und Antwort beziehen sich nicht speziell auf PostgreSQL: Transaction isolation and reading from multiple tables on SQL Server Express and SQL Server 2005
Beispiel
Sagen wir, ich habe 3 Tabellen:
bricks
brickworks (primary key)
completion_time (primary key)
has_been_sold
brick_colors
brickworks (primary key, foreign key pointing to "bricks")
completion_time (primary key, foreign key pointing to "bricks")
quadrant (primary key)
color
brick_weight
brickworks (primary key, foreign key pointing to "bricks")
completion_time (primary key, foreign key pointing to "bricks")
weight
Eine Ziegelei produziert einen Stein auf einmal. Es erzeugt Ziegelsteine, die in jedem ihrer 4 Quadranten verschiedene Farben haben können.
Jemand analysiert später die Bausteine, um ihre Farbkombination zu bestimmen, und schreibt die Ergebnisse in die Tabelle brick_colors.
Jemand anders analysiert die Bausteine, um ihr Gewicht zu bestimmen, und schreibt die Ergebnisse in die Tabelle brick_weight.
Zu einem bestimmten Zeitpunkt kann ein vorhandener Baustein eine aufgezeichnete Farbe haben oder nicht und kann ein aufgezeichnetes Gewicht aufweisen oder nicht.
Eine Anwendung vorhanden ist, und diese Anwendung erhält Wort, dass jemand will (an dieser Stelle auf die Anwendung von seiner Ziegelei/completion_time zusammengesetzte Schlüssel bereits bekannt) einen bestimmten Ziegel kaufen.
Die Anwendung möchte alle bekannten Eigenschaften des Bausteins auswählen. DIE GENAUE ABFRAGE WIRD BEGINNT.
Wenn Farbe oder Gewicht Informationen MID-TRANSACTION hinzugefügt wird, will die Anwendung nicht darüber wissen.
Die Anwendung möchte SEPARATE QUERIES ausführen (kein SELECT mit mehreren JOINs zu den Tabellen mit Fremdschlüsselverknüpfungen, die aufgrund der Tabelle brick_colors möglicherweise mehrere Zeilen zurückgeben).
Dieses Beispiel ist absichtlich einfach; Der Wunsch, dies ohne einen SELECT mit mehreren JOINs zu tun, wäre klarer, wenn mein Beispiel beispielsweise 10 mit Fremdschlüssel verknüpfte Tabellen enthält und viele oder alle von ihnen mehrere Zeilen für denselben Primärschlüssel zurückgeben könnten (wie z. B. brick_colors in der Beispiel wie ich es oben habe).
Versuchte Lösung
Hier ist, was ich mit so weit habe kommen:
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE READ ONLY ;
-- All this statement accomplishes is telling the database what rows should be returned from the present point-in-time in future queries within the transaction
SELECT DISTINCT true
FROM bricks b
LEFT JOIN brick_colors bc ON bc.brickworks = b.brickworks AND bc.completion_time = b.completion_time
LEFT JOIN brick_weight bw ON bw.brickworks = b.brickworks AND bw.completion_time = b.completion_time
WHERE b.brickworks = 'Brick-o-Matic' AND b.completion_time = '2017-02-01T07:35:00.000Z' ;
SELECT * FROM brick_colors WHERE b.brickworks = 'Brick-o-Matic' AND b.completion_time = '2017-02-01T07:35:00.000Z' ;
SELECT * FROM brick_weight WHERE b.brickworks = 'Brick-o-Matic' AND b.completion_time = '2017-02-01T07:35:00.000Z' ;
COMMIT ;
Es scheint nur verschwenderisch, dass zuerst verwenden SELECT mit der Serialisierung ausschließlich für Zwecke der Sicherstellung beitritt.
Gibt es eine andere Möglichkeit, dies zu tun?
Referenzen
PostgreSQL Concurrency Control
PostgreSQL Transcation Isolation
PostgreSQL SET TRANSACTION statement
Danke! Ich habe festgestellt, dass ich in meiner Frage eine falsche Annahme gemacht habe. Ich denke, Sie haben völlig Recht, dass "Repeatable Read" der Weg ist, hier zu gehen. Ich stimme auch zu, dass die Anzahl der Tabellen und ihre Verknüpfung irrelevant ist - ich hielt sie nur aufgrund meiner schlechten Annahme für relevant. Ich werde eine weitere Frage stellen, zu der mich deine Antwort geführt hat. Danke nochmal für die ausführliche Antwort! – rvrabbit
Neue Frage geschrieben! http://stackoverflow.com/questions/42322730/time-when-postgresql-isolation-level-takes-effect-seem-to-bea-after-first-select – rvrabbit