sql >> Database teknologi >  >> RDS >> Sqlserver

Hvorfor indsætte TSQL-sætningsblok, når transaktionsisolationsniveau for en anden transaktion kan serialiseres med et ikke-konfliktende filter?

Det første problem i dit testscenarie er, at tabellen ikke har noget nyttigt indeks på firstname . Det andet er, at bordet er tomt.

Fra Key-Range Locking i BOL

Der er ikke noget passende indeks til at tage RangeS-S låser på, så for at sikre serialiserbar semantik skal SQL Server låse hele tabellen.

Hvis du prøver at tilføje et klynget indeks på tabellen i kolonnen for fornavn som nedenfor og gentage eksperimentet ...

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

... du vil opdage, at du stadig er blokeret!

På trods af at der nu findes et passende indeks, og udførelsesplanen viser, at det er søgt ind for at tilfredsstille forespørgslen.

Du kan se hvorfor ved at køre følgende

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 
 

Returnerer

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

SQL Server udtager ikke bare en rækkeviddelås på præcis det område, du angiver i din forespørgsel.

For et lighedsprædikat på et unikt indeks, hvis der er en matchende nøgle, vil det bare tage en almindelig lås i stedet for en hvilken som helst type rækkelås overhovedet.

For et ikke-entydigt søgeprædikat udtager den låse på alle matchende nøgler inden for området plus den "næste" i slutningen af ​​området (eller på ffffffffffff for at repræsentere uendelighed, hvis der ikke eksisterer en "næste" nøgle). Selv slettede "ghost"-poster kan bruges i dette område nøglelåsning.

Som beskrevet her for et lighedsprædikat på enten et unikt eller ikke-entydigt indeks

Så med en tom tabel er SELECT stadig ender med at låse hele indekset. Du skal også tidligere have indsat en række mellem abc og lmn og så ville din indsættelse lykkes.

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


  1. MySQL - CASE vs IF Statement vs IF funktion

  2. Nye Oracle-kompatibilitetsfunktioner i PostgresPlus Advanced Server 9.3Beta

  3. Behøver jeg virkelig at gøre mysql_close()

  4. Hurtigste måde at fjerne ikke-numeriske tegn fra en VARCHAR i SQL Server