Какие знаешь типы блокировок бд?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Типы блокировок в базе данных
Основные типы блокировок
Блокировка БД — это механизм, который предотвращает одновременный доступ нескольких процессов к одному и тому же объекту (строка, таблица, страница), обеспечивая целостность данных и избегая конфликтов.
1. Уровень блокировок по гранулярности
Row-level блокировка (на уровне строк)
Блокируется только одна строка таблицы.
Типы:
- Shared (S) — читающая блокировка, позволяет другим процессам читать данные
- Exclusive (X) — исключительная блокировка, препятствует всем другим операциям
-- PostgreSQL: читающая блокировка на строку
BEGIN;
SELECT * FROM documents FOR SHARE;
-- Другие процессы могут читать, но не могут менять
-- Исключительная блокировка на строку
SELECT * FROM documents FOR UPDATE;
-- Другие процессы не могут ни читать, ни писать
COMMIT;
Плюсы: высокая конкурентность, многие процессы могут работать одновременно
Минусы: больше памяти на блокировки, сложнее реализовать
Page-level блокировка (на уровне страниц)
Блокируется целая страница БД (обычно 4 КБ или 8 КБ).
-- Пример: операция затрагивает несколько строк
UPDATE documents
SET status = 'processed'
WHERE created_date > '2026-01-01'
-- Блокируются все страницы, содержащие эти строки
Используется: SQL Server, MySQL (InnoDB дефолтно использует row-level)
Table-level блокировка (на уровне таблицы)
Блокируется вся таблица.
-- MySQL: эксклюзивная блокировка на всю таблицу
LOCK TABLES documents WRITE;
INSERT INTO documents VALUES (...);
UNLOCK TABLES;
-- PostgreSQL: блокировка таблицы
LOCK TABLE documents IN EXCLUSIVE MODE;
-- Другие сеансы ждут разблокировки
Плюсы: просто реализовать, минимум памяти
Минусы: низкая конкурентность, другие процессы блокируются
2. Типы блокировок по режиму
Shared Lock (читающая блокировка)
Позволяет нескольким процессам одновременно читать данные.
-- 1С: ВЫБРАТЬ с блокировкой для чтения
ВЫБРАТЬ
*
ИЗ Документ.ПричиндаяНакладная
ДЛЯ ЧТЕНИЯ
Таблица совместимости:
| Shared | Exclusive |
--------|--------|-----------|
Shared | ✓ | ✗ |
Exclusive| ✗ | ✗ |
Exclusive Lock (исключительная блокировка)
Только один процесс может работать с данными, остальные ждут.
-- Исключительная блокировка
SELECT * FROM accounts WHERE account_id = 123 FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE account_id = 123;
-- Другие процессы не могут читать и писать
Таблица совместимости:
| Shared | Exclusive |
---------|--------|-----------|
Shared | ✓ | ✗ |
Exclusive| ✗ | ✗ |
3. Специальные типы блокировок
Intent Lock (намеревающаяся блокировка)
Сигнализирует о намерении заблокировать объект на нижних уровнях.
Иерархия:
Таблица → Intent Shared (IS) или Intent Exclusive (IX)
└─ Страница → Shared (S) или Exclusive (X)
└─ Строка → Shared (S) или Exclusive (X)
Range Lock (блокировка диапазона)
Блокирует диапазон значений, предотвращая phantom read.
-- PostgreSQL: блокировка диапазона
SELECT * FROM orders
WHERE order_date BETWEEN '2026-01-01' AND '2026-01-31'
FOR UPDATE;
Key Lock
Блокирует конкретный ключевой диапазон значений.
-- Предотвращает вставку строк с ключом в диапазон
WHERE order_id BETWEEN 100 AND 200
4. Блокировки в 1С
1С Блокировка объектов
// Процедура ПриСохранении документа
&НаСервере
Процедура ПриСохранении(Отмена)
// 1С использует Exclusive блокировку на документ
// Другие пользователи видят: "Документ заблокирован пользователем ХХХ"
ТекущийДокумент = ЭтотОбъект;
// Выполняем сложные вычисления с блокировкой
РассчитатьСуммы();
// Когда сохраняем — блокировка удерживается до завершения
КонецПроцедуры
Блокировка записей в регистрах
// Установить блокировку на регистр накопления
НаборЗаписей = РегистрНакопления.Товары.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Документ.Значение = ЭтотОбъект;
НаборЗаписей.Отбор.Документ.Использование = Истина;
// При Записи() используется эксклюзивная блокировка
НаборЗаписей.Прочитать();
// ... изменяем ...
НаборЗаписей.Записать();
5. Проблемы, связанные с блокировками
Deadlock (взаимоблокировка)
Процесс 1: Блокирует строку A → ждёт строку B
Процесс 2: Блокирует строку B → ждёт строку A
→ DEADLOCK (взаимная блокировка)
Решение:
-- PostgreSQL: функция для избежания deadlock
BEGIN ISOLATION LEVEL SERIALIZABLE;
-- 1. Всегда берём блокировки в одинаковом порядке
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
SELECT * FROM accounts WHERE id = 2 FOR UPDATE;
COMMIT;
Lock Escalation (повышение уровня блокировки)
Система может автоматически заменить множество row-level блокировок на table-level.
100 блокировок на строки → автоматически переходит на блокировку таблицы
Phantom Read (призрачное чтение)
Транзакция 1: SELECT * WHERE age > 30 [5 строк]
Транзакция 2: INSERT (age = 35)
Транзакция 1: SELECT * WHERE age > 30 [6 строк] ← новая строка
Решение: Range Lock
6. Уровни изоляции транзакций
| Уровень | Phantom | Dirty Read | Non-Repeatable | Блокировка |
|---|---|---|---|---|
| Read Uncommitted | ✓ | ✓ | ✓ | None |
| Read Committed | ✓ | ✗ | ✓ | Row |
| Repeatable Read | ✓ | ✗ | ✗ | Range |
| Serializable | ✗ | ✗ | ✗ | Table |
-- PostgreSQL: установить уровень изоляции
BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM documents WHERE status = 'new' FOR UPDATE;
-- Гарантирует, что никто не добавит новые строки
COMMIT;
7. Оптимизация блокировок
1. Держать блокировку минимум времени
// ❌ Плохо: долгая блокировка
&НаСервере
Процедура ДолгаяОперация()
БлокировкаОбъекта = НовыйОбъект();
БлокировкаОбъекта.Прочитать(); // Блокировка начата
СложныйРасчёт(); // 5 минут вычислений (блокировка держится!)
БлокировкаОбъекта.Записать(); // Блокировка отпущена
КонецПроцедуры
// ✓ Хорошо: минимальная блокировка
&НаСервере
Процедура БыстраяОперация()
РезультатОперации = СложныйРасчёт(); // БЕЗ блокировки
БлокировкаОбъекта = НовыйОбъект();
БлокировкаОбъекта.Прочитать(); // Блокировка начата
БлокировкаОбъекта.Данные = РезультатОперации;
БлокировкаОбъекта.Записать(); // Блокировка отпущена (быстро)
КонецПроцедуры
2. Использовать SELECT FOR UPDATE с WHERE
-- ✓ Хорошо: блокируются только нужные строки
SELECT * FROM documents
WHERE document_id = 123
FOR UPDATE;
-- ❌ Плохо: блокируется всё
SELECT * FROM documents
FOR UPDATE;
3. Избегать циклических зависимостей
// ❌ Плохо
Процедура ОбновитьДокументы()
Для Каждого Док1 Из Документы1 Цикл
Док1.Прочитать(); // ← блокировка
Для Каждого Док2 Из Документы2 Цикл
Док2.Прочитать(); // ← вложенная блокировка (deadlock!)
КонецЦикла;
КонецЦикла;
КонецПроцедуры
// ✓ Хорошо
Процедура ОбновитьДокументы()
Для Каждого Док1 Из Документы1 Цикл
Док1.Прочитать();
КонецЦикла;
Для Каждого Док2 Из Документы2 Цикл
Док2.Прочитать();
КонецЦикла;
КонецПроцедуры
Понимание типов блокировок критично для написания высокопроизводительного и надёжного кода, особенно в многопользовательской системе.