← Назад к вопросам

Какие знаешь типы блокировок бд?

2.3 Middle🔥 191 комментариев
#Блокировки и транзакции#СУБД и хранение

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Типы блокировок в базе данных

Основные типы блокировок

Блокировка БД — это механизм, который предотвращает одновременный доступ нескольких процессов к одному и тому же объекту (строка, таблица, страница), обеспечивая целостность данных и избегая конфликтов.

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. Уровни изоляции транзакций

УровеньPhantomDirty ReadNon-RepeatableБлокировка
Read UncommittedNone
Read CommittedRow
Repeatable ReadRange
SerializableTable
-- 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.Прочитать();
    КонецЦикла;
КонецПроцедуры

Понимание типов блокировок критично для написания высокопроизводительного и надёжного кода, особенно в многопользовательской системе.