linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it worksскоро
  • Уроки
  • База знаний
  • Собеседование
home/postgres/lessons/pg-lab-23-1-lightweight-predicate-locks

lesson ── postgres-labs ── ~22 мин ── 5 шагов

Прочитай wait events и предикатные блокировки

Сначала ты заставишь бэкенд ждать тяжёлую блокировку и опознаешь это по wait_event. Потом откроешь транзакцию на уровне Serializable и найдёшь её предикатные блокировки SIReadLock - те, что ничего не блокируют, а только метят прочитанное.

Вкладки: psql-a, psql-b - две сессии, psql-ops - наблюдатель. В каждой сначала запусти psql.

▶ интерактивный sandbox

Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.

запустить sandbox →

stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя

Шаги

  1. 01

    A блокирует строку

    Вкладка psql-a, запусти psql:

    sql
    BEGIN;
    SELECT * FROM bookings WHERE book_ref = '000001' FOR UPDATE;

    Строка под замком FOR UPDATE. Транзакцию держим открытой.

    подсказка

    FOR UPDATE - сильнейший режим блокировки строки.

    ✓ A держит строку 000001.

  2. 02

    B хочет ту же строку и встаёт в очередь

    Вкладка psql-b, запусти psql:

    sql
    BEGIN;
    SELECT * FROM bookings WHERE book_ref = '000001' FOR UPDATE;

    Команда повисла. Предскажи wait_event_type для B, прежде чем проверять.

    подсказка

    Ожидание тяжёлой блокировки относится к типу Lock.

    ✓ B стоит с wait_event_type = Lock - ждёт строку.

  3. 03

    Опознай ожидание и расчисти

    Вкладка psql-ops, запусти psql и посмотри, на чём стоят бэкенды:

    sql
    SELECT pid, state, wait_event_type, wait_event
    FROM pg_stat_activity WHERE state != 'idle';

    B показывает Lock / transactionid - ждёт завершения A. Теперь освободи очередь: в psql-a сделай COMMIT, затем в psql-b, когда строка достанется ему, сделай ROLLBACK. Проверим, что никто не ждёт.

    подсказка

    После COMMIT в A блокировка строки спадает, и B получает её.

    ✓ Очередь пуста. Переходим к предикатным блокировкам.

  4. 04

    Открой транзакцию на Serializable

    Вкладка psql-a (psql уже запущен). Открой транзакцию на сильнейшем уровне изоляции и прочитай данные:

    sql
    BEGIN ISOLATION LEVEL SERIALIZABLE;
    SELECT count(*) FROM flights WHERE departure = 'SVO';

    Чтение на Serializable оставляет метки SIReadLock - «я это читала». Они никого не блокируют. Оставь транзакцию открытой и предскажи: появятся ли строки SIReadLock в pg_locks?

    подсказка

    SIReadLock возникает именно при чтении на уровне Serializable.

    ✓ Предикатные блокировки появились - чтение оставило следы.

  5. 05

    Разгляди предикатные блокировки на таблице

    Вкладка psql-ops:

    sql
    SELECT locktype, relation::regclass, mode
    FROM pg_locks WHERE mode = 'SIReadLock';

    Метки стоят на flights - на кортежах, странице или всей таблице (PostgreSQL огрубляет гранулярность, когда строк много). Это механизм обнаружения, а не ожидания: если другая транзакция запишет туда, где стоит метка, и шаблон окажется опасным, на коммите будет ошибка 40001. Закоммить транзакцию A (COMMIT).

    подсказка

    relation в pg_locks для SIReadLock указывает на flights.

    ✓ Предикатные блокировки стоят на flights. SSI следит за чтениями.

Что ты узнал

Под тяжёлыми блокировками лежат лёгкие LWLock и spinlock - их видно только через wait_event, не в pg_locks. Ожидание тяжёлой блокировки - это wait_event_type = Lock. Предикатные блокировки SIReadLock нужны Serializable и не блокируют: это метки прочитанного для поиска опасных зависимостей, конфликт по ним приходит ошибкой 40001 на коммите.

команды

  • SELECT wait_event_type, wait_event FROM pg_stat_activity WHERE state='active';на чём ждут бэкенды
  • SELECT mode FROM pg_locks WHERE mode='SIReadLock';предикатные блокировки SSI
  • BEGIN ISOLATION LEVEL SERIALIZABLE;включить SSI, чтения метят SIReadLock

концепции

  • · wait_event_type/wait_event - общий язык ожиданий: Lock, LWLock, IO, Client
  • · LWLock и spinlock не попадают в pg_locks, только в wait_event
  • · SIReadLock не блокирует - это метка прочитанного для Serializable
  • · конфликт SSI приходит ошибкой 40001 на коммите, требует ретрая

← предыдущая

Воспроизведи и прочитай взаимоблокировку

следующая →

Проследи запрос по стадиям и раскрой представление

Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки