sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgres pg_try_advisory_lock blockerar alla poster

Du anropar pg_try_advisory_lock() en gång per rad i hela uppsättningen som skannas (som en del av filtreringen som sker i where klausul), medan du bara vill att den ska anropas en gång per rad i tabell1 returneras av frågan.

Du kan försöka använda en underfråga eller en CTE istället:

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 lita inte på att det nödvändigtvis fungerar som förväntat heller:Postgres bör frestas att skriva om det som din ursprungliga fråga var.

En annan möjlighet är detta, eftersom select en del av ett uttalande utvärderas mycket sent i frågan:

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 verkliga problemet i praktiken är att pg_try_advisory_lock() är något du normalt hittar i appland eller i en funktion, snarare än i en fråga som du gör. På tal om vilket, beroende på vad du gör, är du säker på att du inte ska använda select … for update ?

Angående din uppdatering:

Ja. På grund av limit 1 , det kommer att hitta en match och omedelbart sluta. Vad som förmodligen händer är dock att det inte utvärderar where klausul i samma ordning beroende på dina frågor. SQL erbjuder ingen garanti för att a <> 0 del i a <> 0 and b / a > c utvärderas först. Tillämpat på ditt fall ger det ingen garanti att det rådgivande låset erhålls efter raden från a är sammanfogad med b.




  1. Laravel kapslade relationer

  2. Flask :sqlalchemy.exc.ProgrammingError:(psycopg2.ProgrammingError) relationsanvändare existerar inte

  3. ORA-12557 TNS:protokolladapter kan inte laddas

  4. Hur man skapar anpassade genvägar i SQL Server Management Studio (SSMS) - SQL Server / TSQL handledning Del 10