Являются ли отдельные операторы UPDATES атомарными, независимо от уровня изоляции? (SQL Server 2005) - PullRequest
1 голос
/ 18 сентября 2009

В приложении пользователи и случаи имеют отношение многие ко многим. Пользователи часто выбирают свой список дел. Пользователи могут обновлять один случай за раз (1-10 секундная операция, требующая более одного ОБНОВЛЕНИЯ). В соответствии с READCOMMITTED, любой используемый Вариант заблокирует всех связанных Пользователей от получения их списка Вариантов. Кроме того, самые последние данные - это горячая точка как для чтения, так и для записи в таблицу дел.

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

Я не знаю ни одного собственного способа показать, какие записи являются грязными, поэтому я думаю, что для каждого обновления или вставки в Cases будет установлен флаг INUSE. Этот флаг должен быть очищен к концу транзакции обновления так, чтобы при READCOMMITTED этот флаг никогда не показывался установленным. Обратите внимание, что это НЕ заменяет управление параллелизмом, а только показывает, какие записи потенциально грязны для пользователя.

Мой вопрос заключается в том, является ли это надежным - если мы ОБНОВЛЯЕМ два или более полей (INUSE плюс другие поля) в одном операторе, возможно ли, чтобы параллельный запрос NOLOCK считывал некоторые из новых значений, но не другие? Если это так, можно ли гарантировать, что INUSE будет установлен первым?

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

Спасибо!

Ответы [ 2 ]

1 голос
/ 18 сентября 2009

Решая проблему, просто чтобы быть уверенным: пользователь A при подключении A обновляет два столбца (col1, col2) в MyTable. Пока это происходит, пользователь B в соединении B выполняет грязное чтение, выбирая данные из этой строки. Вы задаетесь вопросом, может ли пользователь B получить, скажем, обновленное значение в col1 И старое / не обновленное значение в col2. Правильно?

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

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

0 голосов
/ 18 сентября 2009

Рассматривали ли вы использование SNAPSHOT уровня изоляции? При использовании для запроса он не требует никаких блокировок и дает именно ту семантику, которую вы запрашиваете:

показывает значения, как они были до любой связанной транзакции, поэтому данные сразу доступны и всегда согласованы (но частично устарели)

...