Ich habe eine Auswahl in SQL Server, die die gesamte Tabelle sperrt.
Hier ist das Setup-Skript (stellen Sie sicher, dass Sie nichts überschreiben)
USE [master]
GO
IF EXISTS(SELECT 1 FROM sys.databases d WHERE d.name = 'LockingTestDB')
DROP DATABASE LockingTestDB
GO
CREATE DATABASE LockingTestDB
GO
USE [LockingTestDB]
GO
IF EXISTS(SELECT 1 FROM sys.tables t WHERE t.name = 'LockingTestTable')
DROP TABLE LockingTestTable
GO
CREATE TABLE LockingTestTable (
Id int IDENTITY(1, 1),
Name varchar(100),
PRIMARY KEY CLUSTERED (Id)
)
GO
INSERT INTO LockingTestTable(Name) VALUES ('1')
INSERT INTO LockingTestTable(Name) VALUES ('2')
GO
Öffnen Sie ein neues Abfragefenster und führen Sie die folgende (wartende) Transaktion aus:
USE [LockingTestDB]
GO
BEGIN TRANSACTION
SELECT * FROM LockingTestTable t WITH (UPDLOCK, ROWLOCK) WHERE t.Name = '1'
WAITFOR DELAY '00:01:00'
COMMIT TRANSACTION
--ROLLBACK
GO
USE [master]
GO
Und noch eine, die ausgeführt wird (stellen Sie sicher, dass sie zur gleichen Zeit ausgeführt werden):
USE [LockingTestDB]
GO
SELECT * FROM LockingTestTable t WITH (UPDLOCK, ROWLOCK) WHERE t.Name = '2'
USE [master]
GO
Sie werden feststellen, dass die zweite Abfrage von der ersten Abfrage blockiert wird. Stoppen Sie die erste Abfrage und führen Sie den ROLLBACK aus. Die zweite Abfrage wird abgeschlossen.
Warum passiert dies?
PS: Durch Hinzufügen eines nicht gruppierten Index (mit vollständiger Abdeckung) über Name wird Folgendes behoben:
USE [LockingTestDB]
GO
CREATE NONCLUSTERED INDEX [IX_Name] ON [dbo].[LockingTestTable]
(
[Name] ASC
)
INCLUDE ( [Id]) WITH (STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Wieder warum?