Я использую SQL Server 2005 Express.
В сценарии я добавил Begin Transaction
команду непосредственно перед INSERT
оператором в хранимой процедуре. Когда я выполнил эту хранимую процедуру, она заблокировала всю таблицу, и все одновременные соединения отображали зависший экран до тех пор, пока это не INSERT
закончилось.
Почему вся таблица блокируется и как мне решить эту проблему в SQL Server 2005 Express?
Edited
Запрос, как показано ниже:
INSERT INTO <table2> SELECT * FROM <table1> WHERE table1.workCompleted = 'NO'
Ответы:
Этот ответ может оказаться полезным для первоначального вопроса, но в первую очередь для устранения неточной информации в других сообщениях. Это также выдвигает на первый план раздел ерунды в BOL.
Связанный раздел BOL гласит:
Примечание: по состоянию на 2014-8-27 BOL был обновлен, чтобы удалить неверные утверждения, приведенные выше.
К счастью, это не так. Если бы это было так, вставки в таблицу происходили бы последовательно, и все считыватели были бы заблокированы из всей таблицы до завершения транзакции вставки. Это сделало бы SQL Server таким же эффективным сервером баз данных, как NTFS. Не очень.
Здравый смысл подсказывает, что этого не может быть, но, как указывает Пол Рэндалл: « Сделай себе одолжение, никому не доверяй ». Если вы не можете никому доверять, включая BOL , я думаю, нам просто нужно это доказать.
Создайте базу данных и заполните фиктивную таблицу кучей строк, отметив возвращенный DatabaseId.
Настройте трассировку профилировщика, которая будет отслеживать события «зафиксировано: получено» и «заблокировано: освобождено», отфильтрована по DatabaseId из предыдущего сценария, задана путь к файлу и отмечен возвращенный TraceId.
Вставьте строку и остановите трассировку:
Откройте файл трассировки, и вы должны найти следующее:
Последовательность принятых блокировок:
Замки затем отпускаются в обратном порядке. Ни в коем случае не было эксклюзивной блокировки на столе.
Да, именно так. SQL Server (и, возможно, любой механизм реляционных баз данных) не имеет представления о том, какие другие пакеты могут выполняться при обработке оператора и / или пакета, поэтому последовательность получения блокировки не меняется.
Для этого конкретного примера взяты те же самые блокировки. Не верь мне, попробуй!
источник
Я не делаю много работы с T-SQL, но читаю документацию ...
Это сделано так, как указано в НАЧАЛО СДЕЛКИ :
И, как указано в документации INSERT , он получит эксклюзивную блокировку на столе. Единственный способ сделать SELECT для таблицы - это использовать
NOLOCK
или установить уровень изоляции транзакции.источник