Как механизмы блокировки (Пессимистический/Оптимистический) связаны с уровнями изоляции транзакций базы данных?

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

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

Как эти две разные концепции связаны друг с другом? Если возможно, простейшим примером.

Ответ 1

Обе эти вещи связаны с согласованностью данных и параллельным доступом, но они представляют собой два разных механизма.

Блокировка предотвращает параллельный доступ к некоторому объекту. Например, когда вы пытаетесь обновить элемент списка todo, пессимистическая блокирующая база данных помещает блокировку строки в запись до тех пор, пока вы не совершите или откатите транзакцию, чтобы никакая другая транзакция не разрешала обновлять одну и ту же запись. Оптимистическая блокировка - это проверка на стороне приложения, изменила ли временная метка/версия записи между извлечением и попыткой ее обновления. Это независимо от уровня изоляции транзакции.

Изоляция транзакций - это согласованность чтения.

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

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

SESSION 1                                  SESSION 2
--------------------------------           --------------------------------------
SELECT count(*) FROM test;
=> 10
                                           INSERT INTO test VALUES ('x');

SELECT count(*) FROM test;
=> 10 with read committed/serializable
=> 11 with read uncommited (dirty read)
                                           COMMIT;

SELECT count(*) FROM test;
=> 10 with serializable
=> 11 with read uncommitted/read committed

Существует четыре уровня изоляции транзакций по ANSI (один из них не упоминается в примере выше, это "повторяемое чтение" ), все из них, кроме сериализуемых, подвержены некоторым аномалиям. Обратите внимание, что это не имеет никакого отношения к блокировке.

Вы можете взглянуть на документацию Oracle на этот здесь, концепции довольно универсальны.

Наконец, ваш подход к использованию оптимистической блокировки кажется разумным для веб-приложения. Скорее всего, вы получаете элемент списка и обновляете его в двух разных HTTP-запросах. Невозможно (или, по крайней мере, неразумно) сохранять транзакцию открытой с явной блокировкой записи после извлечения (как вы узнаете, будет ли второй запрос вообще приходить?) Оптимистическая блокировка обрабатывает это изящно.

Ответ 2

Механизмы блокировки обычно используются для реализации уровней изоляции транзакций. Таким образом, уровни изоляции транзакций определяют контракт, как ваши транзакции должны вести себя одновременно. Механизмы блокировки - это детали реализации.

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

Импорт заключается в том, что механизмы блокировки отличаются между механизмами базы данных. Если вы пишете приложение для одной базы данных, и через некоторое время вы измените движок db, ваше приложение может вести себя по-другому или какая-то его часть может потребовать перезаписи.

Мой совет от пятнадцатилетней разработки бизнес-приложений не должен полагаться на явную блокировку.