Вопрос по sql-server – Мне нужна блокировка на уровне строк

3

Это расширениеВозможно ли принудительное блокирование на уровне строк в SQL Server?, Вот пример использования

У меня есть таблица счетов с номерами счетов, балансами и т. Д. Эта таблица используется многими приложениями. Вполне возможно, что когда я изменяю учетную запись, кто-то другой изменяет другую учетную запись. Таким образом, ожидаемое поведение заключается в том, что я заблокирую свой аккаунт (ROW), а другое использование заблокирует его (еще один ROW).

Но SQL Server 2008 R2 увеличивает эту блокировку до страницы / таблицы, и второй пользователь получает исключение тайм-аута. Я перепробовал все решения, упомянутые в указанном вопросе, но ничего не работает.

Как заставить SQL Server блокировать только блокировку на уровне строк ИЛИ как я могу изменить эту модель таким образом, чтобы она работала с блокировкой страниц / таблиц?

EDIT Обновление предназначено для отдельной записи через его PK, и оно индексируется, поэтому обновляется / блокируется только ОДНА СТРОКА, и процесс занимает не более минуты

Edit Now it looks something weird is happening. I am using an ORM library for DAL which is opening more than one connections and i have raised the question to their support. But, for testing purpose, i opened two sessions on query tool and did following

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 не поддерживает (с параметрами по умолчанию / без ключевых слов), поэтому, похоже, проблема в библиотеке.

Сколько всего записей вы ожидаете иметь в этой таблице? Сколько пользователей у вас на сайте? Nilish
Повторно отредактируйте 2: у вас есть незафиксированная транзакция в первом сеансе, конечно, время второго сеанса истекло Arvo
сейчас я тестирую с двумя пользователями и нет. записей 13000. Мой тест не прошел даже при одном обновлении, но я собираюсь заблокировать 7 записей. bjan
Если бы вы действительно заперлиsingle row с вашим одним обновлением, тогда второе обновление, также предназначенное только для одной строки, должно работать очень хорошо. В вашем SQL Server должно происходить что-то еще, или у вас может быть какая-то неправильная конфигурация .... marc_s
Нет, не должно. Сервер SQL не знает, хотите ли вы зафиксировать или откатить транзакцию, и поэтому он не возвращает никакого значения для этой записи. Как я уже говорил где-то, блокировка SQL (и транзакции) не предназначены для блокировки доступа пользователей к каким-либо данным - они предназначены для сохранения согласованности базы данных. Arvo

Ваш Ответ

2   ответа
8

... так что именно вам нужно ??

Если вы заблокируете более определенного количества строк (примерно 5000), то SQL Server сделаетlock escalation (блокируйте таблицу вместо более чем 5000 строк по отдельности), чтобы оптимизировать производительность и оптимизировать использование ресурсов, но это хорошо! :-)

Есть способы отключить это полностью - но этоNOT recommended! поскольку вы работаете с очень фундаментальным механизмом в механизме хранения SQL Server.

Увидеть:

MSDN docs on lock escalation Adam Machanic blog on lock escalation Introduction to Locking in SQL Server - also has scripts to visualize which process is locking what exactly (rows, page, table, type of lock etc.)
Когда транзакция завершается (или откатывается), SQL Server снимает соответствующие блокировки
If you lock more than a certain amount of rows (roughly 5000), then SQL Server will do lock escalation (lock the table instead of more than 5000 rows individually) Итак, когда работа сделана. Блокировка будет снята. автоматически или мы должны делать это вручную?
Я делаю фиктивное обновление для блокировки записей, и это фиктивное обновление использует поля первичного ключа. Когда я пытаюсь обновить другую запись в другом сеансе, он продолжает ждать ... это блокировка на уровне строк !!! bjan
@Nilish: вам нужно «пакетировать» если вы импортируете фрагменты размером менее 5 000 строк каждый, то у вас не возникнет проблем с эскалацией блокировки
В случае, если я делаю импорт из Excel в SQL Server и записи в Excel более 50 000. Есть ли шанс вставить отдельную запись в ту же таблицу другим пользователем?
2

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

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

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

Или используйте внутренние специальные функции SQL-сервера для таких случаев. Смотри сюда:Функция sp_getapplock в MSDN; таким образом, вы не должны беспокоиться о том, что записи хранятся навсегда и т. д.

Опять же, вся таблица будет заблокирована, если вы заблокируете более 5000 строк по отдельности
Я предложил НЕ использовать блокировку SQL для этого сценария, а создать собственную логику. Мы сделали это для нашего финансового приложения - пользователи часто начинают редактировать документы и переходят на ланч, прежде чем нажать Ctrl + S :)
Программно-определяемый подход к блокировке строк является хорошей идеей (т. Е. Просто иметь свое собственное поле блокировки и связанную логику) до тех пор, пока каждое приложение, использующее базу данных, соблюдает ее, что не так в первоначальном вопросе.
Я блокирую только одну строку, и это будет меньше минуты, в то время как другой пользователь блокирует другую строку. Будь я беру одну минуту или 10, другой пользователь не должен ждать, поскольку он блокирует другую запись bjan
Почему вы блокируете строки вообще? Обычно блокировки необходимы только при записи изменений в базу данных, что занимает миллисекунды (если не выполняется какой-либо медленный код запуска). Если вы хотите заблокировать пользователей от одновременного изменения записей, то внутренняя блокировка сервера SQL не предназначена для этого.

Похожие вопросы