Как выполнить блокировку строки? - PullRequest
8 голосов
/ 22 сентября 2010

Я хочу заблокировать одну запись, и тогда никто не сможет внести изменения в эту запись. Когда я снимаю блокировку, люди могут изменить запись.

Тем временем, когда запись заблокирована, я хочу показать пользователю предупреждение о том, что запись заблокирована и изменения не допускаются.

Как я могу это сделать?

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

Что я могу сделать, чтобы заблокировать запись и запретить все изменения?

Я использую SQL Server 2008

Ответы [ 4 ]

9 голосов
/ 22 сентября 2010

Предполагая, что это сервер MS SQL, вы, вероятно, хотите UPDLOCK, возможно, в сочетании с ROWLOCK ( Таблица подсказок ). У меня проблемы с поиском достойной статьи, которая описывает теорию, но вот быстрый пример:

SELECT id From mytable WITH (ROWLOCK, UPDLOCK) WHERE id = 1 

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

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

<ч />

Кроме того, Вы не должны использовать этот метод для блокировки записей во время ожидания ввода пользователя . Если это ваше намерение, то вместо этого вам следует добавить в таблицу какой-нибудь столбец «изменяемых».

Механизмы блокировки сервера SQL действительно подходят для использования только для сохранения целостности данных / предотвращения взаимных блокировок - транзакции обычно должны быть максимально короткими и, конечно, не должны поддерживаться во время ожидания ввода данных пользователем.

1 голос
/ 22 сентября 2010

Sql Server имеет подсказки по блокировке, но они ограничены областью запроса.

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

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

0 голосов
/ 07 июня 2012

Вы не хотите ждать снятия блокировки и показывать сообщение, как только вы столкнетесь с блокировкой. Если это так, то вы пробовали NOWAIT. См. Табличные подсказки (Transact-SQL) и Табличные подсказки SQL Server 2008 для получения дополнительной информации. Чтобы получить NOWAIT, вам нужно заблокировать записи об изменениях, Google для более подробной информации.

0 голосов
/ 22 сентября 2010

См. дублирующий вопрос на SO.

В основном это:

begin tran

select * from [table] with(holdlock,rowlock) where id = @id

--Here goes your stuff

commit tran

Архив

Как-то такможет быть?

update t 
set t.IsLocked = 1 
from [table] t 
where t.id = @id

Где-то в триггере обновления:

if exists (
select top 1 1 
from deleted d 
join inserted i on i.id = d.id
where d.IsLocked = 1 and i.RowVersion <> d.RowVersion)
begin
print 'Row is locked'
rollback tran
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...