PostgreSQL čaká na zámok. Ako nájsť blokujúcu transakciu?
Dotazy stoja, hoci server má voľnú kapacitu. Postup na nájdenie blokujúcej relácie, posúdenie zásahu a nastavenie limitov čakania.

Uloženie objednávky čaká, požiadavky končia timeoutom a CPU databázy neukazuje preťaženie. Jednou z možností je transakcia, ktorá bráni ostatným získať potrebný zámok. Pred reštartom si vytvorte obraz o tom, kto čaká a kto mu stojí v ceste. Nasledujúci postup vychádza z PostgreSQL 18 a bežných transakčných zámkov; pripravené transakcie a advisory locks potrebujú osobitný rozbor.
Najprv potvrďte čakanie na zámok
Pre prvý prehľad použite čítací dotaz: SELECT pid, pg_blocking_pids(pid) AS blockers FROM pg_stat_activity WHERE wait_event_type = 'Lock'; Výsledok ukáže príslušné čakajúce PID a ich blokujúcich predchodcov. Ak je prázdny, nesnažte sa problém nasilu vysvetliť zámkami. Zaznamenajte čas merania a porovnajte ho s konkrétnou zlyhávajúcou požiadavkou.
Uložte si aj názov aplikácie a dotknutú databázu. Pri odovzdávaní diagnostiky obmedzte výpis na potrebné údaje; text dotazu môže obsahovať citlivé hodnoty. Vopred odlíšte pozorovanie od zásahu. Samotné získanie prehľadu nemá byť dôvodom na hromadné rušenie dotazov alebo odpájanie klientov.
Sledujte reťaz až k pôvodnému blokovaniu
pg_blocking_pids() môže vrátiť držiteľa konfliktného zámku aj čakajúcu reláciu, ktorá je v poradí pred vami. Preto pre nájdené PID preverujte aj ich vlastné blokovanie. Prvý predchodca nemusí byť začiatkom problému. Nevyberajte cieľ zásahu iba podľa najdlhšie čakajúcej používateľskej požiadavky; môže byť len ďalšou obeťou v reťazi.
Stav idle in transaction označuje otvorenú transakciu bez práve bežiaceho dotazu. Porovnajte xact_start, application_name a vlastníka relácie. Zobrazenie cudzích podrobností môže vyžadovať pg_read_all_stats. Zistite, či ide o plánovanú dávku, nasadenie alebo zabudnutú operáciu. Dĺžku transakcie posudzujte podľa jej účelu a dopadu, nie podľa univerzálnej hranice.
Zásah vyberte podľa stavu relácie
pg_cancel_backend(pid) ruší aktuálny dotaz, pg_terminate_backend(pid) ukončuje celú reláciu. Pri nečinnej otvorenej transakcii nie je čo rušiť ako bežiaci dotaz. S vlastníkom dohodnite ukončenie transakcie; ROLLBACK v jej pôvodnom spojení zahodí nepotvrdené zmeny. Nepoužívajte COMMIT len preto, aby sa ostatné požiadavky pohli, ak neviete, čo tým potvrdíte.
Pred prípadným ukončením relácie znovu overte jej identitu a dopad na rozpracovanú operáciu. Tieto funkcie vyžadujú príslušné oprávnenia. Hodnota true pri pg_terminate_backend(pid) bez timeoutu potvrdzuje odoslanie signálu, nie dokončené ukončenie. Po zásahu preto skontrolujte reláciu, reťaz blokovania aj výsledok v aplikácii. Jeden úspešný administrátorský príkaz incident neuzatvára.
Obmedzte čakanie a overte používateľský výsledok
lock_timeout obmedzuje každý pokus o získanie zámku; statement_timeout obmedzuje trvanie príkazu. Ak používate oba, kratší lock_timeout umožní osobitne zachytiť čakanie na zámok. SET LOCAL platí len v aktuálnej transakcii. Hodnoty zvoľte podľa operácie a vyskúšajte spolu s obsluhou chyby v aplikácii. Timeout je hranica čakania, nie oprava blokujúcej práce.
Zámky riadkov a tabuliek sa spravidla držia do konca transakcie. Skráťte preto úsek, počas ktorého ich operácia potrebuje; pri viacerých objektoch dodržujte rovnaké poradie prístupu. Zmenu overte súbežnými operáciami v oddelenom prostredí. V produkcii následne porovnajte čakanie a chybovosť a zopakujte pôvodne zlyhávajúce uloženie objednávky. Úspešné načítanie úvodnej stránky tento zápis nepreverí.
- Zaznamenajte čakajúce PID, čas a dotknutú operáciu.
- Prejdite reťaz predchodcov a určte vlastníka blokovania.
- Rozlíšte zrušenie dotazu, rollback a ukončenie relácie.
- Overte uvoľnenie čakania aj skutočný zápis v aplikácii.
Čo si odniesť
Pri blokovaní databázy hľadajte transakciu, ktorá drží ostatné operácie v čakaní. Najprv si uložte dôkazy, potom zvoľte cielený zásah s vlastníkom služby. Oprava je potvrdená až vtedy, keď pôvodná používateľská operácia opäť dokončí svoju prácu.
Dokumentácia a ďalšie čítanie
- PostgreSQL 18: pg_stat_activity and monitoring privileges
- PostgreSQL 18: pg_blocking_pids
- PostgreSQL 18: pg_locks and blocking relationships
- PostgreSQL 18: Server Signaling Functions
- PostgreSQL 18: ROLLBACK
- PostgreSQL 18: lock_timeout and statement_timeout
- PostgreSQL 18: SET LOCAL
- PostgreSQL 18: Explicit Locking


