sql >> Databasteknik >  >> RDS >> Sqlserver

Varför infoga TSQL-satsblock när transaktionsisoleringsnivån för en annan transaktion kan serialiseras med ett icke-konfliktande filter?

Det första problemet i ditt testscenario är att tabellen inte har något användbart index på firstname . Det andra är att tabellen är tom.

Från Key-Range Locking i BOL

Det finns inget lämpligt index för att ta RangeS-S låser så för att garantera serialiserbar semantik måste SQL Server låsa hela tabellen.

Om du försöker lägga till ett klustrat index i tabellen i kolumnen för förnamn enligt nedan och upprepa experimentet ...

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

... du kommer att upptäcka att du fortfarande är blockerad!

Trots att ett lämpligt index nu finns och genomförandeplanen visar att det söks in för att tillfredsställa frågan.

Du kan se varför genom att köra följande

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 

Retur

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

SQL Server tar inte bara ut ett intervalllås på exakt det intervall du anger i din fråga.

För ett likhetspredikat på ett unikt index om det finns en matchande nyckel kommer det bara att ta ett vanligt lås snarare än någon typ av intervalllås alls.

För ett icke unikt sökpredikat tar den ut lås på alla matchande nycklar inom intervallet plus den "nästa" i slutet av intervallet (eller på ffffffffffff för att representera oändligheten om det inte finns någon "nästa" nyckel). Även raderade "ghost"-poster kan användas i detta område med nyckellåsning.

Som beskrivs här för ett likhetspredikat på antingen ett unikt eller icke unikt index

Så med en tom tabell är SELECT slutar fortfarande med att låsa hela indexet. Du måste också tidigare ha infogat en rad mellan abc och lmn och sedan skulle din insättning lyckas.

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


  1. Köra/starta MySQL utan installation på Windows

  2. Escapende kolumnnamn i PDO-satser

  3. PostgreSQL-replikeringsinställningar och underhåll med Ansible

  4. Vilka tecken är faktiskt kapabla att orsaka SQL-injektion i MySQL?