Kann ich Daten auswählen, die in dieselbe nicht festgeschriebene Transaktion eingefügt wurden?

21

Vielleicht ist dies eine dumme Anfängerfrage, aber ich kann nirgendwo eine Antwort finden. Überall lese ich über das, Transaction Isolationwas die Sichtbarkeit von Daten innerhalb der gleichzeitigen Transaktionen löst. Mein Anliegen ist das Verhalten innerhalb einer einzelnen Transaktion.

Wenn ich eine Transaktion starte, einige Daten einfüge, kann ich sie direkt danach auswählen - immer noch innerhalb derselben, aber nicht festgeschriebenen Transaktion? Wenn ja, kann dieses Verhalten in ähnlicher Weise wie die erwähnte Transaktionsisolation bei gleichzeitigen Transaktionen geändert werden?

Um genau zu sein, ziele ich auf PostgreSQL 9.4 ab.

Nummer vier
quelle

Antworten:

17

Ja.
Alles, was Sie in derselben Transaktion getan haben, ist für spätere Befehle in derselben Transaktion sichtbar. Nur nicht zu anderen Transaktionen, bis sie festgeschrieben sind. Dies gilt für alle Isolationsstufen, mit Ausnahme der Fälle, in Read uncommitteddenen "Dirty Reads" möglich sind (dies wirkt sich jedoch nicht auf Ihre Frage per se aus).

Es wird mit dem MVCC-Modell (Multiversion Concurrency Control) implementiert, das auf der TransactionIdBestimmung des Alters und der Sichtbarkeit für jede Tabellenzeile basiert . Jede neue Zeilenversion, die in derselben Transaktion geschrieben wurde, erhält dieselbe xminund wird als "zur selben Zeit" ausgeführt.

Es gibt einen Eckfall für mehrere CTEs (Common Table Expression) im selben Befehl. Man könnte meinen, dass diese sequentiell ausgeführt werden, aber wenn ein CTE nicht auf den anderen verweist, ist ihre Reihenfolge willkürlich. Und alle sehen vom Beginn der Abfrage an denselben Schnappschuss.

Beispiel:

Erweitertes Beispiel:

Erwin Brandstetter
quelle
3

Lass es uns versuchen :

CREATE OR REPLACE FUNCTION public.sp_get_user()
 RETURNS json
 LANGUAGE plpgsql
AS $function$BEGIN

INSERT INTO users (name, password) VALUES ('deadeye', 'test');
RETURN row_to_json(row) FROM (SELECT name, password FROM users WHERE name = 'deadeye') row;

END;$function$

Jetzt lass uns testen:

SELECT sp_get_user();
{"name":"deadeye","password":"test"}

Es klappt ! Wie Erwin sagte, ist alles, was in einer Transaktion gemacht wurde, innerhalb der Transaktion sichtbar. Die Isolierung erfolgt nur zwischen verschiedenen Threads.

DeadEye
quelle