Что такое оптимистическая и пессимистическая блокировки?

Ответ

Оптимистическая и пессимистическая блокировки — это две стратегии управления одновременным доступом к данным (concurrency control) для предотвращения конфликтов.

Оптимистическая блокировка (Optimistic Locking)

Идея: Конфликты происходят редко. Система не блокирует данные при чтении, а «надеется» на лучшее. Блокировка происходит только в момент записи, причем система проверяет, не изменились ли данные с момента их чтения.

Как работает:

  1. Клиент читает данные вместе с их версией (числом или timestamp).
  2. Клиент выполняет необходимые изменения в приложении.
  3. При попытке записать изменения клиент отправляет новые данные и версию, которую он прочитал.
  4. Система обновляет запись только если текущая версия в базе данных совпадает с той, что прислал клиент. После успешного обновления версия увеличивается.
  5. Если версии не совпадают, значит, другой клиент уже успел изменить данные. Транзакция откатывается, и клиенту возвращается ошибка.

Пример в Go (псевдокод):

// 1. Читаем запись и ее версию
var version int
err := db.QueryRow("SELECT name, version FROM products WHERE id = 1").Scan(&name, &version)

// 2. Пытаемся обновить, проверяя версию в WHERE
result, err := db.Exec(
    "UPDATE products SET name = $1, version = version + 1 WHERE id = $2 AND version = $3", 
    "New Name", 1, version,
)

// 3. Проверяем, была ли строка обновлена
rowsAffected, _ := result.RowsAffected()
if rowsAffected == 0 {
    return errors.New("конфликт обновления: данные были изменены другим пользователем")
}
  • Плюсы: Высокая производительность при низкой интенсивности конфликтов, так как нет долгих блокировок.
  • Минусы: При высокой интенсивности конфликтов много транзакций будут откатываться, что снижает эффективность.

Пессимистическая блокировка (Pessimistic Locking)

Идея: Конфликты вероятны. Система блокирует данные сразу при чтении, чтобы никто другой не мог их изменить до завершения транзакции.

Как работает:

  1. Клиент начинает транзакцию и запрашивает данные с явной блокировкой (например, SELECT ... FOR UPDATE).
  2. База данных блокирует выбранные строки. Другие транзакции, пытающиеся получить доступ к этим строкам, будут ждать снятия блокировки.
  3. Клиент выполняет изменения и завершает транзакцию (commit или rollback).
  4. Блокировка снимается.
  • Плюсы: Гарантирует, что транзакция завершится успешно, если она получила блокировку. Идеально для сред с высокой вероятностью конфликтов.
  • Минусы: Снижает параллельность работы системы. Может приводить к deadlock-ам (взаимным блокировкам).