Оптимистическая и пессимистическая блокировка
Сравните SELECT ... FOR UPDATE (пессимистический подход) и шаблоны с версией столбца / WHERE updated_at = ? (оптимистический подход)
«Оптимистическая и пессимистическая блокировка» — бесплатный урок SQL Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL Academy содержит 4 уроков всего.
Две стратегии работы с параллельностью
- Пессимистичная — блокировать строку при чтении; никто другой не сможет ее изменить
- Оптимистичная — не блокировать строку, а при обновлении проверять, что она не изменилась
Пессимистичная стратегия: SELECT ... FOR UPDATE
Заблокировать сейчас, записать позже:
BEGIN;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
-- other transactions cannot lock or update this row
-- compute new balance...
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;FOR SHARE
Блокировка для чтения — другие могут читать, но не могут записывать:
SELECT * FROM orders WHERE id = 1 FOR SHARE;
-- others can SELECT FOR SHARE but cannot UPDATEПлюсы и минусы пессимистичной стратегии
Плюсы: легко рассуждать о поведении, повторные попытки не нужны.
Минусы: снижает параллельность, может вызвать ожидание блокировок и взаимные блокировки.
Оптимистичная стратегия: столбец версии
Читайте строку вместе с версией, а записывайте с условием WHERE version = expected:
BEGIN;
SELECT id, balance, version FROM accounts WHERE id = 1;
-- compute new balance...
UPDATE accounts
SET balance = ?, version = version + 1
WHERE id = 1 AND version = ?;
-- check rows affected: 0 means someone else updated, retryОптимистичная стратегия с updated_at
Та же идея, но вместо явного столбца версии используется updated_at:
UPDATE accounts
SET balance = ?, updated_at = NOW()
WHERE id = ? AND updated_at = ?;
-- If updated_at has changed in the meantime, 0 rows affected — retry.Плюсы и минусы оптимистичной стратегии
Плюсы: высокая параллельность, отсутствие ожидания.
Минусы: запись может завершиться с ошибкой и потребовать повторной попытки; конфликт обнаруживается только во время UPDATE.
Когда выбирать пессимистичную стратегию
Используйте ее для:
- Коротких транзакций с высокой конкуренцией за горячие строки
- Денежных переводов — частично выполненная операция недопустима
- Длительных операций, при которых конфликт вероятен
Когда выбирать оптимистичную стратегию
Используйте ее для:
- Рабочих нагрузок преимущественно на чтение с редкими конфликтами
- API без состояния, где клиент удерживает строку между запросами
- Редактирования на мобильном устройстве или в автономном режиме с последующей синхронизацией
Гибридный подход: FOR UPDATE NOWAIT
Попробуйте установить блокировку; если строка уже заблокирована, немедленно завершитесь с ошибкой и предложите пользователю повторить попытку:
SELECT * FROM accounts WHERE id = 1 FOR UPDATE NOWAIT;
-- ERROR if someone else holds it — user sees a friendly retry messageКонсультативные блокировки
Блокировки на уровне приложения, не связанные с какой-либо строкой:
SELECT pg_try_advisory_xact_lock(hashtext('order:42'));
-- True if you got the lock, false otherwise — useful for cross-row coordination.Не забывайте индексировать цели блокировок
FOR UPDATE без индекса по столбцу в WHERE может заблокировать больше строк, чем ожидалось (блокируются просканированные строки, а не только соответствующие условию).
Тайм-ауты блокировок
Установите lock_timeout, чтобы не ждать бесконечно:
SET lock_timeout = '5s';
BEGIN;
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
-- ERROR if lock not acquired in 5 secondsИтоги
Пессимистичная стратегия блокирует строку, а оптимистичная проверяет ее при записи.
- Пессимистичная: FOR UPDATE — просто, но снижает параллельность
- Оптимистичная: столбец версии — выше параллельность, но нужны повторные попытки
- Выбирайте стратегию в зависимости от рабочей нагрузки и при необходимости сочетайте их
Быстрая проверка
Уменьшение запасов товара в интернет-магазине сопровождается высокой конкуренцией. Какая стратегия блокировок обычно безопаснее?
Часто задаваемые вопросы
Урок «Оптимистическая и пессимистическая блокировка» бесплатный?
Да — полный текст урока «Оптимистическая и пессимистическая блокировка» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс SQL Academy, подпишись на CoddyKit PRO. Курс SQL Academy содержит 4 уроков всего.
Чему я научусь в уроке «Оптимистическая и пессимистическая блокировка»?
Сравните SELECT ... FOR UPDATE (пессимистический подход) и шаблоны с версией столбца / WHERE updated_at = ? (оптимистический подход) Ты практикуешь SQL Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать SQL Academy?
Предыдущий опыт не требуется. SQL Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Оптимистическая и пессимистическая блокировка»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке SQL Academy?
Да. Каждый урок SQL Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Свойства ACID и аномалии
- Уровни изоляции: READ COMMITTED, REPEATABLE READ, SERIALIZABLE
- Взаимные блокировки: обнаружение и предотвращение
- Оптимистическая и пессимистическая блокировка