Как правиьно заблокировать запись

AlexanderVS
Дата: 29.01.2001 10:06:28
Ситуация следующая: приложение-клиент считывает запись из БД и помещает
данные в форму для редактирования, процедура редактирования длится,
предположим, 1-20 минут, далее пользователь нажимает ОК и не серваке
запускается SP, а в качестве параметров передаются отредактированные данные.
Как правильно заблокировать эту запись, на время редактирования каким-нибудь
клиентом?

--
Всех благ, Александр.
Dmitry
Дата: 29.01.2001 12:48:47
Можно ввести дополнительное поле (например, Block). Приложение-клиент будет обращаться к серверу через SP. В SP кроме выборки данных будет производиться апдейт этого поля, значением, говорящем что запись заблокирована. При записи отредактированной записи, соответственно в Block будет писаться 'разрешающее' значение. Стоит также подумать над тем, что клиент прочитав запись для редактирования может не нажать кнопку OK по причине сбоя компьютера, либо по прихоти пользователя. В этом случае запись останется заблокированной и никто прочитать ее не сможет. Для того, чтобы избежать этого, стоит ввести еще одно поле - время когда произведена блокировка. В дальнейшем при каждом обращении к таблицу через данную SP сначала сравнивать для каждой заблокированной записи разницу между текущим временем и временем блокировки с некоторым заранее заданным лимитом. И если эта разница больше, то сделать принудительно разблокировать запись. В принципе можно, конечно производить эту операцию автоматически, например, каждую минуту, но это создаст большую и при этом ненужную нагрузку на сервер.
Oleg F
Дата: 29.01.2001 14:37:56
Мой ответ см. в корне этой конференциии, называется "Используйте SELECT". Это я по ошибке не сюда отправил, а уровнем выше.
Dmitry
Дата: 29.01.2001 15:23:47
По правде говоря, я не очень силен в средствах блокирвок SQL сервера, так что могу ошибаться, но мне казалось, что в любом случае блокировка распространяется до окончания транзакции на которую эта блокировка наложена. В данном же случае, происходит считывание данных и последующее их редактирвание. Т.е. транзакция уже двано закончена и SQL сервер отдыхает. Поэтому на мой взгляд придется все таки извращаться, так как по окончании транзакции блокировка будет снята и второй пользователь сможет редактировать ту же запись.
Кстати, в зависимости от клиента может не только заканчиваться транзакция, но и обрубаться коннект к серверу (например если клиентом является Internet Explorer а пишем на ASP)
Или я все же не прав?
Oleg F
Дата: 29.01.2001 16:31:27
Почему транзакция давно закончена и SQL сервер отдыхает?
Транзакция начинается и заканчивается тогда, когда этого хочет программист, для этого есть команды BEGIN TRANSACTION, COMMIT и ROLLBACK. И пока активна транзакция, запись заблокирована.
Следовательно, последовательность действий такова:

BEGIN TRANSACTION
SELECT ..... (UPDLOCK) ....
-- дальше пользователь редактирует данные в экранной форме
-- и длится это несколько минут
UPDATE ... (-- или вызов хранимой процедуры, которая делает UPDATE и т.п.)
COMMIT TRANSACTION -- это если пользователь решил сохранить результаты редактирования,
-- в противном случае ROLLBACK


Ну а тем, которые обращаются к этой записи (т.е. другим клиентам) нужно не забывать устанавливать SET LOCK_TIMEOUT, если они не желают ждать разблокирования записи
несколько минут.
SergSuper
Дата: 29.01.2001 16:37:31
...но если вдруг у заблокировавшего юзера отвалиться коннект, то запись может на час-другой остаться заблокированной.

Может быть всё-таки использовать метод Dmitry-я или вообще не блокировать, а проверять перед апдейтом, не была ли запись изменена другим юзером.
Dmitry
Дата: 29.01.2001 17:05:17
Коннект может не только отвалиться (в результате какой-либо неполадки), но он ДОЛЖЕН быть порушен в некоторых случаях. Когда доступ к базе осуществляется через WEB, то крайне нежелательно сохранять коннект после загрузки страницы. То есть работать в принципе будет, но очень не рекомендуется поскольку нагрузка на Web узел может очень сильно возрасти. Хотя, если заранее точно известно что множество пользователей не будут на него набрасываться, то можно и сохранять коннект, но тем не менее остается вероятность того, что коннект отвалится сам по себе. Также он отвалится в случае превышения тайм аута бездействия (окончание сессии), который выставляется на IIS.
Проверять не была ли запись изменена другим пльзователем в принципе можно, но лично меня бы обидело, если бы я после 20 мин (по условию) редактировал запись и как оказалось зазря. И в адрес такой системы пошло бы много нехороших слов.
Oleg F
Дата: 29.01.2001 18:08:44
Когда коннект отваливается, то SQL Server автоматически откатывает транзакцию, связанную с этим коннектом (если она была активна). Соответственно все блокировки этого коннекта снимаются сервером автоматически.
Если SQL Server это по каким-то причинам не делает (а это изредка бывает, у пользователя уж и компьютер выключен, а SQL Server всё думает, что коннект ещё существует), то только потому, что Microsoft не славится надёжностью ни в области ОС, ни в области СУБД. Но в версии SQL 7.0 такие "повисшие" коннекты случаются крайне редко, это в SQL 6.5 была большая проблема.
Garya
Дата: 29.01.2001 23:27:44
Во всех источниках, которые мне попадались, сильно акцентируется, что нельзя блокировать записи, по ка пользователь выполняет некоторую интерактивную обработку. Ведь как может случиться? Некий Вася Пупкин заблокирует записи, не закончив операцию пойдет попить чайку. потом его вызовет на часик-другой директор, а потом он умчиться в срочную командтровку, забыв выключить компьютер. В результате записи так и останутся заблокированными на длительное время. Если тебя не забросает тухлыми помидорами сам Вася Пупкин, то это сделают остальные юзвери, которым этот самый Вася Пупкин не дает нормально работать. Из всех зол следует выбирать меньшее.
AlexanderVS
Дата: 30.01.2001 04:43:49
А если все-таки мы открываем транзакцию и говорим SELECT...(UPDLOCK).... , то блокируется строка или страница?
Еще мне предлогали пронумировать все таблицы, а в отдельную таблицу писать № таблицы и ИД блокируемой записи, а после OK or Cancel, удалять запись о блокировке. Этот метод тоже по моему приемлем?
Всех благ, Александр.