Как я могу безопасно выйти из СУБД, когда записи заблокированы? - PullRequest
3 голосов
/ 15 ноября 2010

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

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

Ответы [ 5 ]

2 голосов
/ 15 ноября 2010

Вот как это обычно делается с SQL Server.Выпущенные разработчиком «блокировки записей» не имеют отношения к архитектуре клиент-сервер.Вы путаете архитектуру разделяемых файлов с архитектурой клиент-сервер.

Убедитесь, что в таблице есть столбец меток времени (который автоматически обновляется ядром базы данных).

Прочитайте в нужной строкередактировать.Поместите метку времени из строки в переменную.

Оператор обновления выглядит следующим образом:

update myTable
set col = {some value}
where id = {your id}
AND
timestampcolumn = {the timestamp the row had when you read it in}

Если кто-то изменил строку с момента ее прочтения, он будет иметь другую метку времени ини одна запись не будет соответствовать условиям вашего условия WHERE, поэтому обновление не будет выполнено.Затем вы можете решить, что делать.

Вы можете отключить клиентский ПК от сети при использовании SQL-Server (или Oracle или любой другой клиент-серверной архитектуры), не оказывая негативного влияния на сервер..

1 голос
/ 15 ноября 2010

В C # вы можете использовать блоки try-catch-finally и выполнить уборку в finally.(Который должен выполняться независимо от того, что).

Вы можете добиться почти того же самого, создав класс, реализующий IDisposable, который получает блокировку и освобождает ее при вызове метода удаления.Затем всякий раз, когда вы используете этот класс (который получает блокировку), вставляйте в блок использования

using (RecordLockingThing myThing = new RecordLockingThing())
{
    //DoStuff
}
//Now myThing is out of scope, and will have been disposed.

Просто убедитесь, что ваш RecordLockingThing правильно и безопасно снимает блокировку в методе утилизации.

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

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

0 голосов
/ 15 ноября 2010

Я удивлен, что никто, кажется, не упомянул sp_getapplock , и это родственник.Если вы оставляете одно соединение открытым для сервера (и блокировка принадлежит Session, а не Transaction), блокировка будет сохранена.Если соединение разорвано (например, на клиентском компьютере произошел сбой), то, как и для всех внутренних блокировок в SQL Server, блокировки будут сняты.

По сути, это способ заставить SQL Server использоватьте же механизмы блокировки, которые он использует внутренне для ваших прикладных целей.

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

0 голосов
/ 15 ноября 2010

У меня была похожая проблема с приложением DMS, на стороне сервера я использовал объект сеанса, набор активных пользователей, каждый клиент обновляет объект сеанса каждые 5 минут. Поэтому, если строка заблокирована и пользователь, который ее заблокировал, больше не находится в объекте сеанса, я освобождаю его. Для этой разблокировки я запускаю фоновый поток на стороне сервера, который каждую минуту сканирует заблокированные строки.

0 голосов
/ 15 ноября 2010

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

Повторное завершение работы пользователя;просто отследите, какие у вас есть блокировки, и снимите их; p

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...