UPDLOCK सेलेक्ट्स हैंग होने (लॉक) का कारण क्यों बनता है?


13

मुझे 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

फिर क्यों?

जवाबों:


19

जैसा कि पुस्तकें ऑनलाइन में प्रलेखित है , UPDLOCKअद्यतन ताले लेता है और उन्हें लेनदेन के अंत में रखता है।

एक सूचकांक के बिना पंक्ति का पता लगाने के लिए, सभी परीक्षण किए गए पंक्तियों को बंद कर दिया जाता है, और लेन-देन पूरा होने तक योग्यता पंक्तियों पर ताले लगाए जाते हैं।

पहला लेन-देन उस पंक्ति पर एक अद्यतन लॉक रखता है जहां नाम = 1. दूसरा लेन-देन अवरुद्ध हो जाता है जब वह उसी पंक्ति पर एक अपडेट लॉक प्राप्त करने का प्रयास करता है (यदि उस पंक्ति के लिए नाम = 2 का परीक्षण करने के लिए)।

एक सूचकांक के साथ, SQL सर्वर जल्दी से केवल उन पंक्तियों का पता लगा सकता है और लॉक कर सकता है जो योग्य हैं, इसलिए कोई संघर्ष नहीं है।

आपको लॉकिंग संकेत के कारण को मान्य करने के लिए एक योग्य डेटाबेस पेशेवर के साथ कोड की समीक्षा करनी चाहिए, और यह सुनिश्चित करने के लिए कि उपयुक्त सूचकांक मौजूद हैं।

संबंधित जानकारी: पढ़ें प्रतिबद्ध स्नैपशॉट अलगाव के तहत डेटा संशोधन

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.