2012-04-23 6 views
6

Penso che ci deve essere qualcosa di base Non sto capendo sul blocco di consulenza in postgres. Se entro i seguenti comandi sul client a riga di comando psql, la funzione restituisce vero entrambe le volte:Acquisire blocchi di avviso in postgres

SELECT pg_try_advisory_lock(20); --> true 
SELECT pg_try_advisory_lock(20); --> true 

mi aspettavo che il secondo comando deve restituire falso, dal momento che il blocco dovrebbe essere già stato acquisito. Stranamente, io capisco quanto segue, suggerendo che il blocco è stato acquisito due volte:

SELECT pg_advisory_unlock(20); --> true 
SELECT pg_advisory_unlock(20); --> true 
SELECT pg_advisory_unlock(20); --> false 

Quindi credo che la mia domanda è, come si fa a acquisire un blocco di consulenza in un modo che si ferma restando acquisito di nuovo?

+8

Dalla stessa sessione è possibile acquisire lo stesso blocco tutte le volte che si desidera; ma è necessario rilasciarlo lo stesso numero di volte o chiudere la sessione prima che un'altra sessione possa acquisire il blocco. – kgrittn

risposta

11

E se provassi a farlo dalle 2 diverse sessioni di PostgreSQL?

Scopri di più in the docs.

+2

Ah, vedo, quindi una volta che una sessione ha acquisito un blocco, può acquisirlo di nuovo, ma un'altra sessione non può. Grazie! – foldl

3

La mia prima impressione sui blocchi di avviso era simile. Mi aspettavo che la seconda query (SELECT pg_tryadvisory_lock (20)) restituisse anche false (perché il primo ha ottenuto il blocco). Ma questa query ha solo confermato che un bigInt con valore 20 ha un lock. L'interpretazione spetta all'utente.

Immaginate che l'avviso blocchi come una tabella in cui è possibile memorizzare un valore e ottenere un blocco su quel valore (normalmente un BigInt). Non è un blocco esplicito e nessuna trascrizione sarà ritardata. Dipende da te come interpretare e utilizzare il risultato - e non sta bloccando.

Lo uso nei miei progetti con le opzioni di due interi. SELEZIONA pg_try_advisory_lock (classId, objId) considerando che entrambi i parametri sono numeri interi.

Per farlo funzionare con più di una tabella basta usare l'OID della tabella come CLASSID e l'id primario (qui 17) come ObjId:

SELECT pg_try_advisory_lock((SELECT 'first_table'::regclass::oid)::integer, 17);

In questo esempio "prima_tabella" è il il nome della tabella e il secondo intero è l'id della chiave primaria (qui: 17).

L'utilizzo di un parametro bigInt come consentito consente un intervallo più ampio di ID, ma se lo si utilizza con "second_table" rispetto all'id 17 viene bloccato anche (perché è stato bloccato il numero "17" e non la relazione a una riga specifica in un tavolo).

Mi ci è voluto un po 'di tempo per capirlo, quindi spero che aiuti a capire il funzionamento interno dei blocchi di consulenza.

+0

Non ho capito questo ... mi riferisci a 'ma se lo usi con" second_table "rispetto all'id 17 è bloccato pure" come mai id 17 sarebbe bloccato nel caso precedente con il seguente blocco di avviso quando uso la seguente query 'SELECT pg_try_advisory_lock ((SELECT 'first_table' :: regclass :: oid) :: integer, 17);' – Viren