Оптимистичный параллелизм — нет ли проблемы?

#sql-update #multi-user #optimistic-concurrency #pessimistic-locking

#sql-обновление #многопользовательский #оптимистичный-параллелизм #пессимистичный-блокировка

Вопрос:

Я прочитал статью.

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

Вам, как пользователю, необходимо:

  1. Извлеките строку и последнее изменение dateTime строки.
  2. Выполните необходимые вычисления, но пока ничего не записывайте в БД.
  3. После вычислений, непосредственно перед тем, как вы захотите записать результат в БД, снова извлеките последнее изменение dateTime той же строки.
  4. Сравните дату и время # 1 с dateTime # 2. Если они равны — все в порядке, зафиксируйте и запишите текущее время как дату последнего изменения времени строки. else — здесь был другой пользователь — Откат.

Этот процесс кажется логичным, НО я вижу в нем следующую дыру:

В # 3 пользователь извлекает последнее изменение dateTime строки, но что, если между чтением этого dateTime (в # 3) и временем записи в # 4 другой пользователь вводит, записывает свои данные и выходит? Первый пользователь никогда не узнает об этом, и это переопределит данные второго пользователя.

Разве это невозможно?

Ответ №1:

У алгоритма, который вы описываете, действительно есть возможность пропустить одновременное обновление между шагами # 3 и # 4.

В части, посвященной тестированию на наличие нарушений оптимистичного параллелизма, говорится:

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

Хотя это и не упоминается явно, идея заключается в том, чтобы этап сравнения и обновления выполнялся атомарно на сервере. Это можно сделать с помощью инструкции UPDATE, содержащей предложение WHERE, включающее временную метку и ее исходное значение. Аналогично примеру, упомянутому в статье, где все исходные значения столбцов в строке по-прежнему соответствуют значениям, найденным в базе данных.