SQL Server 2012: почему разные значения в предложении where блокируют запрос на выборку?

Наше приложение выполняет эти два запроса:

select   A.* from   LETTUREAPERTE A
where IDAZIENDAOPERATORE=3

и

select   A.* from   LETTUREAPERTE A
where IDAZIENDAOPERATORE=2

по идентификатору компании, которую рассматривает пользователь. Ну, пока второй запрос выполняется корректно, первый блокируется и никогда не выполняется. В LETTUREAPERTE таблицах меньше 400 записей, в некоторых IDAZIENDAOPERATORE по 2, в некоторых по 3.

Я не знаю, почему это происходит и почему первый запрос блокируется... Я получаю эту ошибку в конце. Я получаю сообщение об ошибке, говорящее о том, что процесс был выбран в качестве жертвы взаимоблокировки.

Транзакция (идентификатор процесса 62) заблокирована на ресурсах блокировки другим процессом и выбрана в качестве жертвы взаимоблокировки. Повторите транзакцию.

Я даже выполнил несколько запросов, чтобы определить, есть ли какие-либо блокировки обновления для некоторых записей этой таблицы, но их нет. Так и должно быть, потому что за весь проект мы ни разу не использовали UPDLOCK в запросах...


person SagittariusA    schedule 26.01.2017    source источник
comment
Добавьте with option (recompile), чтобы узнать, получится ли у вас лучший план выполнения.   -  person Gordon Linoff    schedule 26.01.2017
comment
Эм, а где мне добавить with option (recompile)? Что это за заявление?   -  person SagittariusA    schedule 26.01.2017
comment
select A.* from LETTUREAPERTE A where IDAZIENDAOPERATORE=2 with option(recompile).. но я не думаю, что это может повлиять на таблицу с 400 записями. Можете ли вы опубликовать график взаимоблокировки   -  person TheGameiswar    schedule 26.01.2017
comment
Я получаю тот же результат... иногда выполнение занимает 80 секунд. В других случаях это прерывается, как я уже говорил...   -  person SagittariusA    schedule 26.01.2017
comment
вы можете вставить план выполнения сюда, чтобы поделиться им, если хотите: brentozar.com/pastetheplan   -  person Tanner    schedule 26.01.2017
comment
@Tanner: это мой план казни, если вы хотите взглянуть, даже если я не знаю, о чем вы говорите: brentozar.com/pastetheplan/?id=ryXnL5vve   -  person SagittariusA    schedule 26.01.2017
comment
@LoryLory, так LETTUREAPERTE - это вид? Можете ли вы поделиться его определением? В этом плане есть несколько огромных прочтений.   -  person Gareth Lyons    schedule 26.01.2017
comment
да, это очень часто используемое представление... теперь я выполняю UPDATE STATISTICS [dbo].[TABLE] WITH FULLSCAN для каждой таблицы, участвующей в представлении... как вы понимаете, происходит массовое чтение?   -  person SagittariusA    schedule 26.01.2017
comment
что вы имеете в виду под определением, его запросом?   -  person SagittariusA    schedule 26.01.2017
comment
@LoryLory да, спасибо за запрос (как в части выбора создания представления как выбора ......). Вы можете увидеть количество прочтений (значение фактического количества строк), наведя указатель мыши на каждое поле на плане — из пары таблиц считывается 11 миллионов строк. Я также нигде не вижу предиката, основанного на IDAZIENDAOPERATORE = something, поэтому я думаю, что это производное значение.   -  person Gareth Lyons    schedule 26.01.2017


Ответы (4)


Попробуйте запустить sp_WhoIsActive от Adam Mechanic и отследить транзакцию, которая может использовать тот же источник таблицы. После этого найдите этот объект в sp_lock (системный). Исходя из этого, вы должны получить некоторое представление о том, почему у вас возникла эта тупиковая ситуация. Возможно, значение 2 не используется тем же (заблокированным) индексом во время выполнения, что и значение 3, что возможно при использовании отфильтрованных индексов в таблице.

person Bartosz X    schedule 26.01.2017
comment
Простите, я не могу понять из документации, как использовать эти процедуры... Если я запускаю exec sp_WhoIsActive, он говорит, что такой процедуры не существует. Я знаю почти все об этих магазинах... - person SagittariusA; 26.01.2017
comment
ссылка — в блоге авторов вы найдете все, что вам нужно. В основах — просто выполните его без каких-либо параметров, и это покажет вам все активные транзакции в вашем экземпляре SQL Server вместе с их идентификаторами сеансов. На основе этого идентификатора вы можете выполнить ссылку sp_lock, чтобы увидеть какой объект затронут (в основном, чтобы увидеть, пытаетесь ли вы получить доступ к объекту, который в данный момент используется другим процессом. - person Bartosz X; 26.01.2017
comment
Я посмотрю... Я не знаю, разрешено ли мне загружать и устанавливать внешние библиотеки, так как на прошлой неделе мы получили криптографический шкафчик на нашем втором производственном сервере... Я спрошу у своего руководителя группы разработчиков - person SagittariusA; 26.01.2017
comment
Это один из наиболее часто используемых и одобренных администраторами баз данных ;-) если нет, попробуйте хотя бы встроенный 'sp_who2' - он покажет вам все (кроме самого запроса), и вы должны отфильтровать его самостоятельно как это также включает системные транзакции. - person Bartosz X; 26.01.2017
comment
Я только что выполнил связанный здесь запрос (sqlservergeeks.com/sys-dm_tran_active_transactions) и Я заметил, что есть 6 активных транзакций только для чтения, которые начались 6 часов назад... должен ли я закрыть их? - person SagittariusA; 26.01.2017
comment
Если вы единственный человек, который использует эту среду, то да, сделайте это. Но если это живое производство, то, возможно, попробуйте поговорить с вашим администратором баз данных перед этим ;-) - person Bartosz X; 26.01.2017
comment
Эти старые транзакции называются worktables. Если я хорошо понимаю, это системная транзакция, так что... ничего полезного. По-видимому, ничто не мешает чтению чего-либо... так что это загадка, почему это так медленно. - person SagittariusA; 26.01.2017
comment
это мой план выполнения, если хотите посмотреть, даже если я не знаю, о чем вы говорите: brentozar.com/pastetheplan/?id=ryXnL5vve - person SagittariusA; 26.01.2017
comment
Давайте продолжим обсуждение в чате. - person Bartosz X; 26.01.2017
comment
@ Бартош X, спасибо, приятель, за твою ценную помощь. Кажется, теперь все работает лучше. Если хотите, посмотрите мой обновленный ответ, чтобы узнать, что именно я сделал ... Я также добавил план обслуживания для еженедельного обновления статистики. Искренне благодарю вас, вы были очень добры ко мне. - person SagittariusA; 27.01.2017

Одной из возможностей является незафиксированная/откатная транзакция в одной из строк с 3.

Если вы используете транзакции, вам нужно использовать TRY/CATCH и либо зафиксировать, либо откатить.

Вы можете попробовать использовать (NOLOCK):

select   A.* from   LETTUREAPERTE A (NOLOCK)
where IDAZIENDAOPERATORE=3

Другой вариант — перезапустить SQL-сервер, чтобы посмотреть, устранит ли это проблему, но, скорее всего, она повторится.

person apc    schedule 26.01.2017
comment
Даже если я использую (NOLOCK) в запросе, я получаю тот же результат... Я не знаю, есть ли заблокированные транзакции, которые следует удалить. Есть ли способ получить это? - person SagittariusA; 26.01.2017
comment
stackoverflow.com/questions/4449719/ - person apc; 26.01.2017
comment
Спасибо за помощь. Я уже пробовал этот запрос и проверил, что нет открытой транзакции... - person SagittariusA; 26.01.2017

как предлагает Гордон в комментарии, добавьте опцию перекомпиляции, как показано ниже.

select   A.* from   LETTUREAPERTE A
where IDAZIENDAOPERATORE=2 OPTION (RECOMPILE)
person Moudiz    schedule 26.01.2017
comment
Я получаю тот же результат... иногда выполнение занимает 80 секунд. В других случаях это прерывается, как я уже говорил... - person SagittariusA; 26.01.2017
comment
вы пропустили ключевое слово with перед option, не уверены, что это варианталь, не так ли?! - person Tanner; 26.01.2017
comment
с тех пор, как 10 минут назад у меня больше не было ошибок ... просто выполнение занимает слишком много времени. Всегда около 70/80 секунд, и все вместе со мной жалуются, что приложение работает медленно... - person SagittariusA; 26.01.2017
comment
@Tanner это необязательно, как вы упомянули - person Moudiz; 26.01.2017
comment
Поделитесь планом выполнения? - person Bartosz X; 26.01.2017
comment
@BartoszX: план выполнения? - person SagittariusA; 26.01.2017
comment
@BartoszX Я пытался включить план выполнения. На данный момент это то, что я иногда получаю: транзакция (идентификатор процесса 62) была заблокирована на ресурсах блокировки с другим процессом и была выбрана в качестве жертвы взаимоблокировки. Повторите транзакцию. - person SagittariusA; 26.01.2017
comment
@BartoszX, это мой план казни, если хотите посмотреть, даже если я не знаю, о чем вы говорите: brentozar.com/pastetheplan/?id=ryXnL5vve - person SagittariusA; 26.01.2017
comment
@LoryLory попробуйте это dba.stackexchange.com/questions/78683/ - person Moudiz; 26.01.2017
comment
@Moudiz: тоже спасибо, но ничего заблокированного не обнаружено. - person SagittariusA; 26.01.2017
comment
@LoryLory вы должны запустить запрос, а затем запустить выбор в ссылке. чтобы поймать блокировку, должен быть выполнен запрос, этот URL-адрес, я не знаю, может ли он помочь вам сохранить взаимоблокировку msdn.microsoft.com/en-us/library/ms190465.aspx, вы говорите, что эта таблица не содержит много данных, и когда вы ее запускаете, для ее выполнения требуется много времени. значит есть замок. если я неправильно понимаю вопрос - person Moudiz; 26.01.2017

Как предложил мне **Бартош X**, я запустил следующую команду для каждой таблицы, участвующей в представлении:

UPDATE STATISTICS [Schema].[Table_Name] WITH FULLSCAN

Это заняло около часа, но, похоже, ситуация значительно улучшилась. Итак, я добавил следующий план обслуживания для еженедельного выполнения:

введите здесь описание изображения

Если интересно, это запрос моего взгляда:

SELECT        
  IDOPERATORE, 
  COGNOMENOMEOPERATORE, 
  IDAZIENDAOPERATORE,
  (SELECT
     SUM(LETTURERIMASTE) AS Expr1
   FROM dbo.LETTURERIMASTE AS B
   WHERE (IDLOTTOLETTURISTA IN
           (SELECT IDLOTTOLETTURISTA
            FROM dbo.LOTTILETTURISTA AS C
            WHERE (DATAFINELOTTOLETTURISTA >= CONVERT(datetime, ROUND(CONVERT(float, GETDATE()), 0, 1))) AND (IDLETTURISTALOTTOLETTURISTA = A.IDOPERATORE)))) 
   AS LETTURERIMASTE
person SagittariusA    schedule 27.01.2017