Ответ
Оптимистическая и пессимистическая блокировки — это две стратегии управления одновременным доступом к данным (concurrency control) для предотвращения конфликтов.
Оптимистическая блокировка (Optimistic Locking)
Идея: Конфликты происходят редко. Система не блокирует данные при чтении, а «надеется» на лучшее. Блокировка происходит только в момент записи, причем система проверяет, не изменились ли данные с момента их чтения.
Как работает:
- Клиент читает данные вместе с их версией (числом или timestamp).
- Клиент выполняет необходимые изменения в приложении.
- При попытке записать изменения клиент отправляет новые данные и версию, которую он прочитал.
- Система обновляет запись только если текущая версия в базе данных совпадает с той, что прислал клиент. После успешного обновления версия увеличивается.
- Если версии не совпадают, значит, другой клиент уже успел изменить данные. Транзакция откатывается, и клиенту возвращается ошибка.
Пример в 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)
Идея: Конфликты вероятны. Система блокирует данные сразу при чтении, чтобы никто другой не мог их изменить до завершения транзакции.
Как работает:
- Клиент начинает транзакцию и запрашивает данные с явной блокировкой (например,
SELECT ... FOR UPDATE
). - База данных блокирует выбранные строки. Другие транзакции, пытающиеся получить доступ к этим строкам, будут ждать снятия блокировки.
- Клиент выполняет изменения и завершает транзакцию (commit или rollback).
- Блокировка снимается.
- Плюсы: Гарантирует, что транзакция завершится успешно, если она получила блокировку. Идеально для сред с высокой вероятностью конфликтов.
- Минусы: Снижает параллельность работы системы. Может приводить к
deadlock
-ам (взаимным блокировкам).