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

Объркан относно UPDLOCK, HOLDLOCK

Защо UPDLOCK блок избира? Матрицата за съвместимост на заключване ясно показва N за спора за S/U и U/S, както в Без конфликт .

Що се отнася до подсказката HOLDLOCK, документацията гласи:

HOLDLOCK:Еквивалентно на SERIALIZABLE. За повече информация вижте SERIALIZABLE по-нататък в тази тема.

...

SERIALIZABLE:... Сканирането се извършва със същата семантика като транзакция, изпълняваща се на ниво на изолация SERIALIZABLE...

и темата Ниво на изолация на транзакциите обяснява какво означава SERIALIZABLE:

Никакви други транзакции не могат да променят данните, които са прочетени от текущата транзакция, докато текущата транзакция не завърши.

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

Следователно поведението, което виждате, е напълно обяснено от документацията на продукта:

  • UPDLOCK не блокира едновременно SELECT или INSERT, но блокира всяко UPDATE или DELETE на редовете, избрани от T1
  • HOLDLOCK означава SERALIZABLE и следователно позволява SELECTS, но блокира UPDATE и DELETES на редовете, избрани от T1, също така като всеки INSERT в диапазона, избран от T1 (което е цялата таблица, следователно всякак вмъкване).
  • (UPDLOCK, HOLDLOCK):вашият експеримент не показва какво би блокирало в допълнение към случая по-горе, а именно друга транзакция с UPDLOCK в T2 :
    SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
  • TABLOCKX няма нужда от обяснения

Истинският въпрос е какво се опитвате да постигнете ? Играта с намеци за заключване без абсолютно пълно 110% разбиране на заключващата семантика предизвиква проблеми...

След редактиране на ОП:

Бих искал да избера редове от таблица и да предотвратя промяната на данните в тази таблица, докато я обработвам.

Трябва да използвате едно от по-високите нива на изолация на транзакциите. REPEATABLE READ ще предотврати промяната на данните, които четете. SERIALIZABLE ще предотврати промяната на данните, които четете и нови данни от вмъкване. Използването на нива на изолация на транзакциите е правилният подход, за разлика от използването на подсказки за заявка. Kendra Little има хубав плакат, който обяснява нивата на изолация.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Елементите ORDER BY трябва да се появят в списъка за избор, ако е посочено SELECT DISTINCT

  2. Автоматизирайте заданията за архивиране и поддръжка с помощта на план за поддръжка в SQL Server

  3. GROUP BY за комбиниране/свързване на колона

  4. Как мога да направя нещо като:ИЗПОЛЗВАЙТЕ @databaseName

  5. Анализ на MS SQL Server за тези, които го виждат за първи път