मुझे SQL सर्वर में एक चयन मिला है जो पूरी तालिका को लॉक करता है।
यहाँ सेटअप स्क्रिप्ट है (सुनिश्चित करें कि आप कुछ भी अधिलेखित नहीं करते हैं)
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
एक नई क्वेरी विंडो खोलें और निम्नलिखित लेनदेन को चलाएं (जिसमें एक प्रतीक्षा है):
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
और एक और जो चलेगा (सुनिश्चित करें कि वे एक ही समय में चलाते हैं):
USE [LockingTestDB]
GO
SELECT * FROM LockingTestTable t WITH (UPDLOCK, ROWLOCK) WHERE t.Name = '2'
USE [master]
GO
आप देखेंगे कि दूसरी क्वेरी पहले वाले द्वारा ब्लॉक कर दी जाएगी। पहली क्वेरी को रोकें और रोलबैक पर अमल करें और दूसरा पूरा हो जाएगा।
ये क्यों हो रहा है?
पुनश्च: नाम पर एक गैर-संकुलित सूचकांक (पूर्ण कवरेज के साथ) जोड़ना इसे ठीक करेगा:
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
फिर क्यों?