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

Въпрос за SQL Deadlock

SELECT не могат да блокират с други SELECT, защото те придобиват само споделени заключвания. Казвате, че трябва да вземем предвид, че тези SELECT сега „изискват изключителни заключения за четене“, но това не е възможно да вземем предвид, защото 1) няма такова нещо като exlusive read lock и 2) четенията не придобиват изключителни заключвания.

Но вие задавате по-общ въпрос дали простите изявления могат да блокират. Отговорът е категорично, категорично ДА . Заключванията се придобиват при изпълнение, не се анализират предварително и се сортират, след което се придобиват в някакъв ред. Би било невъзможно двигателят да знае предварително необходимите заключвания, тъй като те зависят от действителните данни на диска, и да прочете данните, необходими на двигателя, за да ... заключи данните.

Блокировките между прости оператори (SELECt срещу UPDATE или SELECT срещу DELETE) поради различен ред на достъп до индекса са доста често срещани и много лесни за разследване, диагностициране и коригиране. Но имайте предвид, че има винаги участва операция за запис, тъй като четенията не могат да се блокират взаимно. За тази дискусия добавянето на подсказка UPDLOCK или XLOCK към SELECT трябва да се счита за запис. Дори не се нуждаете от JOIN, вторичният индекс може да въведе проблема с реда за достъп, водещ до блокиране, вижте Блокиране на четене/запис .

И накрая, писане на SELECT FROM A JOIN B или писане на SELECT FROM B JOIN A е напълно без значение. Оптимизаторът на заявките е свободен да пренарежда реда на достъп, както намери за добре, действителният текст на заявката не налага реда на изпълнение по никакъв начин.

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

Страхувам се, че няма рецепта за бисквити. Решението ще зависи от всеки случай. В крайна сметка задънените блокировки в приложенията за бази данни са факт от живота. Разбирам, че това може да звучи абсурдно, както в „ние кацнахме на Луната, но не можем да напишем правилно приложение за база данни“, но има силни фактори, които до голяма степен гарантират, че приложенията в крайна сметка ще се сблъскат с блокиране. Щастливите безизходици са най-лесното справяне с грешките, просто прочетете отново състоянието, приложете логиката, пренапишете новото състояние. Като се има предвид, има някои добри практики, които могат драстично да намалят честотата на задънените блокировки, до точката, в която почти изчезват:

  • Опитайте се да имате последователен модел на достъп за записи . Имайте ясно дефинирани правила, посочващи неща като „транзакцията винаги трябва да таблици в този ред:Customers -> OrderHeaders -> OrderLines .' Обърнете внимание, че поръчката трябва да се спази вътре в транзакция . Общо взето, класирайтевсички таблици във вашата схема и укажете, че всички актуализации трябва да се извършват в ред на класиране. Това в крайна сметка се свежда до дисциплина на кода на отделния участник, който пише кода, тъй като той трябва да гарантира, че пише, че се актуализира в правилния ред в рамките на транзакция.
  • Намалете продължителността на пише. Обичайната мъдрост е следната:в началото на транзакцията направете всички четения (прочетете съществуващото състояние), след това обработете логиката и изчислете нови стойности, след което напишете всички актуализации в края на транзакцията. Избягвайте модел като „четене->запис->логика->четене->запис“, вместо това направете „четене->четене->логика->запис->запис“. Разбира се, истинското майсторство се състои в това как да се справяте с действителни, реални, индивидуални случаи, когато очевидно човек трябва трябва да правите записи по средата на транзакцията. Тук трябва да се каже специална бележка за специфичен тип транзакции:тези, управлявани от опашка, които по дефиниция започват дейността си чрез изваждане от опашката (=запис) от опашката. Тези приложения винаги са били изключително трудни за писане и склонни към грешки (особено блокирания), за щастие има начини да го направите, вижте Използване на таблици като опашки .
  • Намалете броя на четенията. Сканирането на таблици е the най-разпространената причина за блокиране. Правилното индексиране не само ще елиминира задънените блокировки, но може също така да повиши производителността в процеса.
  • Изолиране на моментна снимка . Това е най-близкото нещо, което ще получите до безплатен обяд по отношение на избягването на безизходици. Умишлено го слагам последно, защото може да маскира други проблеми (като неправилно индексиране), вместо да ги коригирате.

Опитвате се да решите този проблем с LockCustomerByXXX подходът, страхувам се, че не работи. Песимистичното заключване няма мащаб. Оптимистична едновременност актуализациите са правилен начин, ако искате да имате някаква прилична производителност.



  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 от един сървър на друг - урок по SQL от Раджан Сингх

  2. Как да създадете таблица в SYS схема в SQL Server?

  3. Скаларно вграждане на UDF в SQL Server 2019

  4. Как да изтрия от множество таблици, използвайки INNER JOIN в SQL сървър

  5. Свързване към именуван екземпляр на SQL Server 2008 от класически ASP