Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Защо тази заявка на SQL Server блокира?

  • процес 9196a8 има страница 151867 слот 174 в режим X и иска страница 140302 слот 31 в режим S
  • процес 88b5b8 има страница 140302 слот 31 в режим X и иска страница 151867 слот 174 в режим S
  • двете изтривания се изпълняват под isolationlevel="repeatable read (3)"

Така че блокировката се появява в базовата купчина на таблицата (RID заключванията вместо заключванията на ключове предполагат купчина, а не Btree). Високото ниво на изолация (вероятно причинено от DTC, съдейки по точното име) прави настройката RCSI неуместна.

Какъв тип са колоните PARTYEXTERNALREF и PARTYTYPE? Подадените параметри са NVARCHAR (т.е. Unicode) и ако колоните са VARCHAR (т.е. Ascii), тогава поради правилата на предимство на типа данни индексът NC няма да се използва. Поради включеното сканиране на таблица, заедно с използваното високо ниво на изолация, блокирането е почти неизбежно.

Решението би било да се използват параметри от типа VARCHAR за @P0 и @P1, така че NC индексът да се използва, за да се избегне сканирането на таблицата.

Ако параметрите вече са от тип VARCHAR и можете да потвърдите от плана за изпълнение, че се използва търсене в NC, първият ми въпрос ще бъде какво друго извършва ли се транзакцията, освен операторите за изтриване?

Между другото, вие давате само името на NC индекса, но предполагам, че е на (PARTYEXTERNALREF, ISCOUNTERPARTY, PARTYID) .

Актуализиране

Тъй като в коментара ви се казва, че колоните са NVARCHAR тогава хипотезата за сканиране на таблиците вероятно е грешна. Има още три възможности за причиняване на блокиране, които се нуждаят от разследване:

  • всеки друг оператор, изпълняван от транзакцията преди DELETE (това е най-вероятно)
  • всяко припокриване в редовете, избрани от два оператора DELETE, участващи в блокировката
  • хеш колизия

Само за първите две хипотези можете да направите всичко точно сега (проверете дали са верни). За последното мога да ви кажа как да го проверите, но не е тривиално. Малко вероятно е да се случи и малко трудно се доказва, но е възможно. Тъй като знаете за случай на блокиране (прикаченият XML), използвайте го като база за разследване:

  • възстановете копие на базата данни към определен момент със спиране на 2011-09-02T19:00:29.690
  • изпълнете DBCC TRACEON(3604,-1)
  • използване на DBCC PAGE (<възстановен идентификатор на база данни>, 1, 151867, 3) проверете стойностите в слот 174
  • с помощта на DBCC PAGE(, 1, 140302, 3)` проверете стойностите в слот 31
  • изпълнете SELECT %%lockres%% FROM PARTIES WHERE PARTYEXTERNALREF =... AND ISCOUNTERPARTY='N' и PARTYID=... и предайте прочетените по-горе стойности
  • сравнява получените хеш стойности на заключване, ако те съвпадат, тогава имате хеш сблъсък и това е причинило блокиране.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изтриване на пощенски профил на база данни в SQL Server (T-SQL)

  2. SQL Server безшумно съкращава varchar в съхранените процедури

  3. Прехвърляне/конвертиране на nvarchar в datetime

  4. Как може LIKE '%...' да търси в индекс?

  5. Как да предадете нулева променлива към SQL съхранена процедура от C#.net код