Что такое блокировка (Lock) в контексте баз данных?

Ответ

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

Основные типы блокировок в СУБД:

  • Разделяемая (Shared Lock, S-Lock): Используется для операций SELECT. Несколько транзакций могут одновременно удерживать разделяемые блокировки на одной строке, но ни одна из них не сможет установить эксклюзивную блокировку, пока существуют разделяемые.
  • Эксклюзивная (Exclusive Lock, X-Lock): Используется для операций модификации (INSERT, UPDATE, DELETE). Только одна транзакция может удерживать эксклюзивную блокировку на объекте, блокируя все другие транзакции (как на чтение, так и на запись).

Уровни изоляции и блокировки: Поведение блокировок напрямую зависит от уровня изоляции транзакции. Например, при уровне READ COMMITTED в PostgreSQL разделяемые блокировки снимаются сразу после чтения строки, а при REPEATABLE READ — удерживаются до конца транзакции.

Явное управление блокировками (на примере PostgreSQL):

-- Начало транзакции
BEGIN;

-- Явная установка эксклюзивной блокировки на строку для обновления.
-- Это пессимистичный подход, предотвращающий "lost update".
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;

-- Выполнение операции с заблокированной строкой
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

COMMIT;

Проблемы, связанные с блокировками:

  • Взаимоблокировка (Deadlock): Когда две или более транзакции бесконечно ожидают снятия блокировок друг с другом. СУБД автоматически обнаруживает deadlock и откатывает одну из транзакций.
  • Блокирование (Lock Contention): Высокая конкуренция за одни и те же данные может привести к очереди ожидания и снижению производительности.

На практике важно проектировать транзакции так, чтобы они были короткими, захватывали блокировки в предсказуемом порядке и использовали подходящий уровень изоляции, чтобы минимизировать негативное влияние на параллелизм.

Ответ 18+ 🔞

А, слушай, про блокировки в базах данных! Это, блядь, такая тема, что если не разобраться, то можно такую хиросиму и нигерсраки устроить в продакшене, что потом волосы дыбом встанут. Короче, представь себе: у тебя несколько транзакций лезут к одной и той же записи. Одна хочет прочитать, другая — обновить, третья — удалить. Если им всем разрешить делать это одновременно, получится пиздопроебибна и бардак в данных. Вот чтобы этого не было, и придумали блокировки — как будто на дверь в сортир вешают табличку «занято».

Основные типы этих самых блокировок:

  • Разделяемая (Shared Lock, S-Lock): Это как книжку в библиотеке почитать. Несколько человек могут одновременно смотреть в одну книгу, да похуй. Но вот вырвать из неё страницу или написать «здесь был Вася» — уже нельзя, пока кто-то читает. Используется для SELECT.
  • Эксклюзивная (Exclusive Lock, X-Lock): А это уже полный контроль. Ты один в сортире, и пока ты не выйдешь, все остальные будут бздеть в очереди. Ни почитать, ни тем более что-то изменить нельзя. Для INSERT, UPDATE, DELETE.

Тут ещё есть нюанс, ёпта: как сильно ты будешь блокировать, зависит от уровня изоляции транзакции. Это как настройка паранойи. Можно блокировку снять сразу после чтения, а можно держать до конца транзакции, чтобы никто даже подозрения ебать не мог, что данные под тобой изменились.

Вот смотри, как это руками делается в PostgreSQL, если совсем не доверяешь автоматике:

-- Начинаем дело
BEGIN;

-- Говорим базе: «Слушай, я сейчас буду работать с записью id=1, и чтобы никто, блядь, даже близко не подходил, пока я не закончу».
-- Это пессимистичный подход, чтоб не было «lost update».
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;

-- Теперь спокойно делаем что надо. Все остальные запросы к этой строке будут ждать.
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

COMMIT;

Но и тут, конечно, свои грабли:

  • Взаимоблокировка (Deadlock): Это когда два чувака встали в дверном проёме и каждый ждёт, чтобы другой посторонился. Оба стоят, и терпения ноль ебать. К счастью, СУБД не дура, она это видит и одного из них впендюрит — откатит его транзакцию, чтобы второй прошёл.
  • Блокирование (Lock Contention): Представь очередь в один сортир на рок-фестивале. Все хотят, а доступ один. Волнение ебать, а производительность системы падает ниже плинтуса.

Так что мораль простая, чувак: делай транзакции короткими, как порох, бери блокировки в одном и том же порядке (чтобы не было deadlock'ов) и не выставляй уровень изоляции «параноик», если можно обойтись «реалистом». А то доверия ебать ноль к системе будет, когда всё начнёт виснуть.