Мне нужна блокировка на уровне строк
Это расширение к Можно ли принудительно блокировать уровень строки в SQL Server?, Вот пример использования
У меня есть таблица счетов с номерами счетов, балансами и т. Д. Эта таблица используется многими приложениями. Вполне возможно, что пока я изменяю учетную запись, кто-то другой изменяет другую учетную запись. Таким образом, ожидаемое поведение заключается в том, что я заблокирую свой аккаунт (ROW), а другое использование заблокирует его (еще один ROW).
Но SQL Server 2008 R2 увеличивает эту блокировку до страницы / таблицы, и второй пользователь получает исключение тайм-аута. Я перепробовал все решения, упомянутые в указанном вопросе, но ничего не работает.
Как заставить SQL Server блокировать только блокировку на уровне строк ИЛИ как я могу изменить эту модель таким образом, чтобы она работала с блокировкой страниц / таблиц?
РЕДАКТИРОВАТЬ Обновление предназначено для одной записи через его PK, и оно индексируется, так что только ОДНА СТРОКА обновляется / блокируется, и процесс занимает не более минуты
Редактировать Теперь выглядит что-то странное происходит. Я использую библиотеку ORM для DAL, которая открывает более одного соединения, и я поднял вопрос к их поддержке. Но для целей тестирования я открыл две сессии на инструменте запросов и сделал следующее
Session # 1
begin tran
UPDATE myTable SET COL_1 = COL_1 WHERE COL_1 = 101;
Session # 2
SELECT COL_1 FROM myTable WHERE COL_1 = 101;
Запрос в сеансе # 2 раза!!! Запросы для других значений COL_1
работают нормально. Теперь выглядит, что SELECT заблокирован для сеанса, если та же запись находится в режиме редактирования в другом сеансе.
Хотя Oracle поддерживает выбор строки (с параметрами по умолчанию / без ключевых слов) во время ее изменения другим сеансом, SQL Server не поддерживает (с параметрами по умолчанию / без ключевых слов), поэтому, похоже, проблема в библиотеке.
2 ответа
SQL Server всегда использует блокировку на уровне строк по умолчанию.... так что именно вам нужно??
Если вы заблокируете более определенного количества строк (примерно 5000), то SQL Server сделает эскалацию блокировки (блокирует таблицу вместо более чем 5000 строк по отдельности), чтобы оптимизировать производительность и оптимизировать использование ресурсов - но это хорошо!:-)
Есть способы полностью отключить это, но это НЕ рекомендуется! так как вы работаете с очень фундаментальным механизмом в механизме хранения SQL Server.
Увидеть:
- Документы MSDN по повышению блокировки
- Блог Адама Маханича о повышении блокировки
- Введение в блокировку в SQL Server - также есть скрипты для визуализации, какой именно процесс блокирует (строки, страница, таблица, тип блокировки и т. Д.)
Представьте, что ваша система является клиент-серверным приложением, где клиент и сервер соединены очень медленной линией (например, обычной почтой), и пользователи очень долго изменяют свои записи (например, неделю). Затем подумайте, когда вам нужно заблокировать строки / данные и когда вы фактически разрешаете изменять строки / данные и т. Д. - очевидно, что размещение внутренних блокировок SQL-сервера на несколько дней больше не кажется хорошей идеей.
Если у вас нет ситуации, когда двум пользователям необходимо изменить одну и ту же запись, вам не нужно блокировать данные при изменении данных вообще. Блокировка требуется только на очень короткий момент, когда записи изменяются в базе данных - другими словами, когда пользователь фиксирует изменения. (Это оптимистический сценарий блокировки.) Конечно, если два пользователя изменяют одни и те же данные, последние изменения будут заменять более ранние.
Если вам абсолютно необходимо, чтобы два пользователя никогда не изменяли одни и те же данные (пессимистическая блокировка), то, вероятно, наиболее общий способ - это использовать некоторые определяемые приложением таблицы блокировок ИЛИ определенные поля в таблицах данных. Когда один пользователь извлекает какую-либо запись (при запуске редактирования или аналогичную), вам необходимо проверить, является ли эта запись уже используемой (заблокированной), а если нет, то пометьте эту запись как заблокированную. Конечно, вам понадобится некоторая функциональность для удаления устаревших блокировок.
Или используйте внутренние специальные функции SQL-сервера для таких случаев. Смотрите здесь: функция sp_getapplock в MSDN; таким образом, вы не должны беспокоиться о хранении записей навсегда и т. д.