2016-04-03 9 views
5

Ist es möglich, Phantom-Lesevorgänge zu verhindern oder eine fehlende Zeile in einer Postgres-Transaktion anderweitig zu sperren? Betrachten wir zum Beispiel die folgende Sequenz von Befehlen:Wie Phantom-Lesevorgänge in Postgres verhindern?

Am Anschluss 1:

CREATE TABLE weather (city varchar(80) PRIMARY KEY); 
BEGIN; 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
INSERT INTO weather VALUES ('a'); 

Zwischenzeit auf Anschluss 2:

BEGIN; 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
SELECT * FROM weather WHERE city = 'a' FOR SHARE; 
INSERT INTO weather VALUES ('b'); 

und zurück zum Anschluss 1:

COMMIT; 

Und wieder zurück zu Verbindung 2:

COMMIT; 
SELECT * FROM weather; 
-- Shows both rows 

Es scheint unmöglich, dass die Transaktion auf Verbindung 2 erfolgreich ist, da die Voraussetzung für die Erstellung der Zeile 'b' von der Abwesenheit der Zeile 'a' abhängig war. Wie verhindere ich, dass die zweite Transaktion erfolgreich ist?

+0

PostgreSQL-Version? –

+0

psql (PostgreSQL) 9.3.11 –

+1

Serialisierbare Transaktionen können erfolgreich ausgeführt werden, solange das Verhalten mit * einigen * seriellen Sortierungen dieser Transaktionen übereinstimmt. Diese Reihenfolge muss jedoch nichts mit der Reihenfolge zu tun haben, in der diese Transaktionen gestartet oder festgeschrieben werden . In diesem Fall sieht es so aus, als ob Sie das gleiche Ergebnis erhalten würden, wenn Sie Transaktion 2 gefolgt von Transaktion 1 ausgeführt hätten. Daher sehe ich keinen Grund für einen Konflikt. –

Antwort

0

Eine Möglichkeit, es zu tun, ohne die gesamte Tabelle Verriegelung wird mit PostgreSQLs Advisory lock [1] Mechanismus:

-- tx 1 
begin; 
select pg_advisory_lock(1234); 
insert/update.... 
commit; 

-- tx 2 
begin; 
select pg_advisory_lock(1234); 
SELECT * FROM weather WHERE city = 'a' FOR SHARE; 
insert/update... 
commit; 

Auf diese Weise können sind inter-Transaktion Kommunikation tun, wo normale MVCC Verhalten ist nicht genug. In dem Beispiel ist 1234 eine beliebige ganze Zahl mit einer Bedeutung auf Anwendungsebene. Siehe auch [2] für weitere Möglichkeiten, mit Advisory-Locks zu arbeiten.

[1] http://www.postgresql.org/docs/9.5/static/explicit-locking.html#ADVISORY-LOCKS

[2] http://www.postgresql.org/docs/9.5/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS-TABLE