sql >> Database teknologi >  >> RDS >> PostgreSQL

Postgres pg_try_advisory_lock blokerer alle poster

Du ringer til pg_try_advisory_lock() én gang pr. række i hele sættet, der bliver scannet (som en del af den filtrering, der forekommer i where klausul), mens du kun vil have det kaldt én gang pr. række i tabel1 returneret af forespørgslen.

Du kan prøve at bruge en underforespørgsel eller en CTE i stedet:

with rows as (
SELECT a.id
FROM table1 a
JOIN table2 b ON a.table1_id = b.id
WHERE table2.id = 1
)
select rows.*
from rows
where pg_try_advisory_lock('table1'::regclass::integer, rows.id);

Men stol heller ikke på, at det nødvendigvis fungerer som forventet:Postgres burde være fristet til at omskrive det, som din oprindelige forespørgsel var.

En anden mulighed er dette, da select en del af en erklæring evalueres meget sent i forespørgslen:

with rows as (
SELECT a.id,
       pg_try_advisory_lock('table1'::regclass::integer, a.id) as locked
FROM table1 a
JOIN table2 b ON a.table1_id = b.id
WHERE table2.id = 1
)
select rows.id
from rows
where rows.locked;

Det virkelige problem i praksis er, at pg_try_advisory_lock() er noget, du normalt ville finde i app-land eller i en funktion, snarere end i en forespørgsel, som du laver. Apropos hvilket, afhængigt af hvad du laver, er du sikker på, at du ikke skal bruge select … for update ?

Angående din opdatering:

Ja. På grund af limit 1 , det kommer til at finde et match og stoppe med det samme. Hvad der dog sandsynligvis sker, er, at det ikke evaluerer where klausul i samme rækkefølge afhængigt af dine forespørgsler. SQL giver ingen garanti for, at a <> 0 del i a <> 0 and b / a > c bliver evalueret først. Anvendt på dit tilfælde giver det ingen garanti for, at den rådgivende lås er opnået efter rækken fra a er sammenføjet med b.




  1. Microsoft annoncerer SQL Server 2012 R2 og SQL Server 2012 R3!

  2. MySQL str_to_date problem

  3. Hvorfor kan jeg ikke oprette forbindelse direkte til min MySQL RDS DB Instance? (Jeg kan kun oprette forbindelse via SSHing til en EC2)

  4. Fjernelse af overlapningstimer fra optællingen af ​​ikke-arbejdsdage