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

Защо да вмъкнете блок на TSQL оператор, когато нивото на изолация на транзакция за друга транзакция може да се сериализира с неконфликтен филтър?

Първият проблем във вашия тестов сценарий е, че таблицата няма полезен индекс на firstname . Второто е, че таблицата е празна.

От Заключване на обхват на ключове в BOL

Няма подходящ индекс за приемане на RangeS-S заключва, така че да гарантира семантика, която може да се сериализира, SQL Server трябва да заключи цялата таблица.

Ако опитате да добавите клъстериран индекс към таблицата в колоната с първо име, както е по-долу, и повторете експеримента...

CREATE CLUSTERED INDEX [IX_FirstName] ON [dbo].[dummy] ([firstname] ASC)

... ще откриете, че все още сте блокирани!

Въпреки факта, че вече съществува подходящ индекс и планът за изпълнение показва, че той се търси, за да удовлетвори заявката.

Можете да видите защо, като стартирате следното

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN

SELECT *
FROM   dummy
WHERE  firstname = 'abc'

SELECT resource_type,
       resource_description, 
       request_mode
FROM   sys.dm_tran_locks
WHERE  request_session_id = @@SPID

COMMIT 

Връща

+---------------+----------------------+--------------+
| resource_type | resource_description | request_mode |
+---------------+----------------------+--------------+
| DATABASE      |                      | S            |
| OBJECT        |                      | IS           |
| PAGE          | 1:198                | IS           |
| KEY           | (ffffffffffff)       | RangeS-S     |
+---------------+----------------------+--------------+

SQL Server не просто премахва заключване на диапазона точно в диапазона, който сте посочили в заявката си.

За предикат за равенство на уникален индекс, ако има съвпадащ ключ, той просто ще отнеме обикновено заключване, а не какъвто и да е тип заключване на диапазон.

За неуникален предикат за търсене той премахва заключвания на всички съвпадащи ключове в диапазона плюс "следващия" в края на диапазона (или на ffffffffffff за представяне на безкрайност, ако не съществува ключ "следващ"). Дори изтрити "призрачни" записи може да се използва в този диапазон за заключване на ключ.

Както е описано тук за предикат за равенство на уникален или неуникален индекс

Така че с празна таблица SELECT все пак в крайна сметка заключва целия индекс. Трябва също така преди това да сте вмъкнали ред между abc и lmn и тогава вашето вмъкване ще успее.

insert into dummy values('def', 'def')


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изпълнете командата Insert и върнете вмъкнат идентификатор в Sql

  2. 4 начина да проверите дали таблица съществува, преди да я пуснете в SQL Server (T-SQL)

  3. Колоните за дата в SQL-Server (MSSQL-JDBC 3.0), работещи под Java 1.7.0, извлечени като 2 дни в миналото

  4. Как да получите време от формат DateTime в SQL?

  5. Как да вмъкна таблица с данни в таблица на база данни на SQL Server?