2016-04-03 15 views
5

È possibile impedire la lettura Phantom o bloccare in altro modo una riga mancante in una transazione Postgres? Ad esempio, si consideri la seguente sequenza di comandi:Come evitare le letture fantasma su Postgres?

Alla connessione 1:

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

Nel frattempo, sulla connessione 2:

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

E torna alla connessione 1:

COMMIT; 

E di nuovo al collegamento 2:

Sembra impossibile che la transazione sulla connessione 2 abbia esito positivo, poiché il presupposto per la creazione della riga 'b' dipendeva dall'assenza della riga 'a'. Come posso impedire che la seconda transazione abbia esito positivo?

+0

PostgreSQL? –

+0

psql (PostgreSQL) 9.3.11 –

+1

Le transazioni serializzabili possono avere successo fintanto che il comportamento è coerente con * alcuni * ordinamenti seriali di tali transazioni, ma questo ordine non deve avere nulla a che fare con l'ordine in cui tali transazioni sono avviate o impegnate . In questo caso, sembra che si otterrebbe lo stesso risultato se si eseguisse la transazione 2 seguita dalla transazione 1, quindi non vedo alcun motivo per un conflitto. –

risposta

0

Un modo di farlo senza bloccare l'intera tabella sta usando di PostgreSQL Advisory lock [1] meccanismo:

-- 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; 

In questo modo si è in grado di fare la comunicazione inter-operazione, in cui il normale comportamento MVCC non è sufficiente. Nell'esempio 1234 è un numero intero arbitrario con un significato a livello di applicazione. Vedi anche [2] per altri modi per lavorare con i blocchi di avviso.

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

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

Problemi correlati