kb/locks
Тяжёлые блокировки отношений и строк, каскад от idle-in-transaction, взаимоблокировки и их диагностика через pg_locks и pg_stat_activity, лёгкие и предикатные блокировки.
Забытый открытый BEGIN держит блокировку до конца транзакции. Если за ним в честной FIFO-очереди встанет ALTER TABLE (ACCESS EXCLUSIVE), то даже совместимые SELECT за ним тоже повиснут - встаёт вся таблица.
Блокировка строки хранится в самой строке (xmax + infomask), а не в pg_locks. Режимов четыре: FOR KEY SHARE, FOR SHARE, FOR NO KEY UPDATE, FOR UPDATE. Слабые нужны, чтобы внешние ключи не сериализовали вставки.
Deadlock - цикл в графе ожидания: каждая транзакция ждёт ту, что ждёт её. PostgreSQL находит его через deadlock_timeout (1 с) и откатывает одну транзакцию с ошибкой 40P01. Лечится единым порядком блокировок.
Под тяжёлыми блокировками лежат лёгкие LWLock (защита структур памяти) и spinlock (пара полей). Их не видно в pg_locks, только в wait_event. Отдельно - предикатные SIReadLock для Serializable, которые не блокируют.
Каждая команда берёт на таблицу блокировку одного из 8 режимов: от ACCESS SHARE (обычный SELECT) до ACCESS EXCLUSIVE (DROP/ALTER), который конфликтует со всеми. Блокировка держится до конца транзакции.