Поделиться через


Оптимистическая конкуренция

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

В оптимистическом параллелизме строка остаётся разблокированной до тех пор, пока не придет время обновить или удалить её. На этом этапе строка перечитается и проверяется, была ли она изменена с момента последнего чтения. Если строка изменилась, обновление или удаление завершается ошибкой и необходимо повторить попытку.

Чтобы определить, изменена ли строка, ее новая версия проверяется на кэшированную версию строки. Эта проверка может зависеть от версии строки, например столбца метки времени в SQL Server или значений каждого столбца в строке. Многие СУБД не поддерживают версии строк.

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

Если оптимистическая согласованность реализована источником данных, приложение задает атрибут инструкции SQL_ATTR_CONCURRENCY в SQL_CONCUR_ROWVER или SQL_CONCUR_VALUES. Чтобы обновить или удалить строку, выполняется позиционированная инструкция обновления или удаления или вызывается SQLSetPos так же, как и с пессимистической конкуренцией, то драйвер или источник данных возвращает SQLSTATE 01001 (конфликт операции курсора), если обновление или удаление не удается из-за конфликта.

Если приложение реализует оптимистическую конкурентность, оно устанавливает для атрибута оператора SQL_ATTR_CONCURRENCY значение SQL_CONCUR_READ_ONLY для чтения строки. Если сравнивает версии строк и если ей неизвестен столбец версий строк, она вызывает SQLSpecialColumns с опцией SQL_ROWVER, чтобы определить имя этого столбца.

Приложение обновляет или удаляет строку, повышая конкурентность до уровня SQL_CONCUR_LOCK (для получения права записи к строке) и выполняя инструкцию UPDATE или DELETE с условием WHERE, которое указывает версию или значения строки на момент их считывания приложением. Если строка изменилась с тех пор, инструкция завершится ошибкой. Если предложение WHERE не однозначно идентифицирует строку, инструкция также может обновить или удалить другие строки; Версии строк всегда однозначно определяют строки, но значения строк однозначно определяют строки, только если они включают первичный ключ.