यह उत्तर मूल प्रश्न के लिए मददगार साबित हो सकता है लेकिन मुख्य रूप से अन्य पोस्टों में गलत जानकारी को संबोधित करना है। यह BOL में बकवास के एक भाग को भी उजागर करता है।
और जैसा कि INSERT प्रलेखन के लिए कहा गया है , यह मेज पर एक विशेष लॉक का अधिग्रहण करेगा। तालिका के विरुद्ध एक चयन का एकमात्र तरीका NOLOCK का उपयोग करना या लेन-देन का अलगाव स्तर निर्धारित करना है।
BOL राज्यों का जुड़ा हुआ भाग:
एक INSERT विवरण हमेशा उस तालिका में एक अनन्य (X) लॉक प्राप्त करता है जिसे वह संशोधित करता है, और लेनदेन पूरा होने तक उस लॉक को रखता है। अनन्य (एक्स) लॉक के साथ, कोई अन्य लेनदेन डेटा को संशोधित नहीं कर सकता है; रीड ऑपरेशंस केवल NOLOCK संकेत के उपयोग के साथ हो सकते हैं या बिना पढ़े हुए आइसोलेशन स्तर को पढ़ सकते हैं। अधिक जानकारी के लिए, डेटाबेस इंजन में लॉकिंग देखें ।
NB: 2014-8-27 के अनुसार BOL को ऊपर उद्धृत गलत कथनों को हटाने के लिए अद्यतन किया गया है।
शुक्र है कि ऐसा नहीं है। यदि यह एक तालिका में आवेषण थे तो क्रमिक रूप से घटित होंगे और सभी पाठक पूरी तालिका से तब तक अवरुद्ध रहेंगे जब तक कि सम्मिलित लेन-देन पूरा नहीं हो जाता। यह SQL सर्वर को NTFS के रूप में डेटाबेस सर्वर के रूप में कुशल बनाता है। बहुत नहीं।
आम समझ से पता चलता है कि ऐसा नहीं हो सकता लेकिन पॉल रान्डेल बताते हैं, " अपने आप पर एक एहसान करो, किसी पर भरोसा मत करो "। अगर आप BOL सहित किसी पर भी भरोसा नहीं कर सकते , तो मुझे लगता है कि हमें इसे साबित करना होगा।
एक डेटाबेस बनाएँ और पंक्तियों के एक समूह के साथ एक डमी तालिका को पॉपुलेट करें, ध्यान दें कि डेटाबेसआईड वापस नहीं आया।
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
USE [master]
GO
IF EXISTS (SELECT name FROM sys.databases WHERE name = N'LockDemo')
DROP DATABASE [LockDemo]
GO
DECLARE @DataFilePath NVARCHAR(4000)
SELECT
@DataFilePath = SUBSTRING(physical_name, 1, CHARINDEX(N'master.mdf', LOWER(physical_name)) - 1)
FROM
master.sys.master_files
WHERE
database_id = 1 AND file_id = 1
EXEC ('
CREATE DATABASE [LockDemo] ON PRIMARY
( NAME = N''LockDemo'', FILENAME = N''' + @DataFilePath + N'LockDemo.mdf' + ''', SIZE = 2MB , MAXSIZE = UNLIMITED, FILEGROWTH = 2MB )
LOG ON
( NAME = N''LockDemo_log'', FILENAME = N''' + @DataFilePath + N'LockDemo_log.ldf' + ''', SIZE = 1MB , MAXSIZE = UNLIMITED , FILEGROWTH = 1MB )
')
GO
USE [LockDemo]
GO
SELECT DB_ID() AS DatabaseId
CREATE TABLE [dbo].[MyTable]
(
[id] [int] IDENTITY(1,1) PRIMARY KEY CLUSTERED
, [filler] CHAR(4030) NOT NULL DEFAULT REPLICATE('A', 4030)
)
GO
INSERT MyTable DEFAULT VALUES;
GO 100
एक प्रोफाइलर ट्रेस सेट करें जो लॉक को ट्रैक करेगा: अधिग्रहित और लॉक: जारी की गई घटनाएं, पिछली स्क्रिप्ट से डेटाबेसआईड पर फ़िल्टर करना, फ़ाइल के लिए एक पथ सेट करना और ट्रेसआईड को नोट करना।
declare @rc int
declare @TraceID int
declare @maxfilesize BIGINT
declare @databaseid INT
DECLARE @tracefile NVARCHAR(4000)
set @maxfilesize = 5
SET @tracefile = N'D:\Temp\LockTrace'
SET @databaseid = 9
exec @rc = sp_trace_create @TraceID output, 0, @tracefile, @maxfilesize, NULL
if (@rc != 0) goto error
declare @on bit
set @on = 1
exec sp_trace_setevent @TraceID, 24, 32, @on
exec sp_trace_setevent @TraceID, 24, 1, @on
exec sp_trace_setevent @TraceID, 24, 57, @on
exec sp_trace_setevent @TraceID, 24, 3, @on
exec sp_trace_setevent @TraceID, 24, 51, @on
exec sp_trace_setevent @TraceID, 24, 12, @on
exec sp_trace_setevent @TraceID, 60, 32, @on
exec sp_trace_setevent @TraceID, 60, 57, @on
exec sp_trace_setevent @TraceID, 60, 3, @on
exec sp_trace_setevent @TraceID, 60, 51, @on
exec sp_trace_setevent @TraceID, 60, 12, @on
exec sp_trace_setevent @TraceID, 23, 32, @on
exec sp_trace_setevent @TraceID, 23, 1, @on
exec sp_trace_setevent @TraceID, 23, 57, @on
exec sp_trace_setevent @TraceID, 23, 3, @on
exec sp_trace_setevent @TraceID, 23, 51, @on
exec sp_trace_setevent @TraceID, 23, 12, @on
-- DatabaseId filter
exec sp_trace_setfilter @TraceID, 3, 0, 0, @databaseid
-- Set the trace status to start
exec sp_trace_setstatus @TraceID, 1
-- display trace id for future references
select TraceID=@TraceID
goto finish
error:
select ErrorCode=@rc
finish:
go
एक पंक्ति डालें और ट्रेस रोकें:
USE LockDemo
GO
INSERT MyTable DEFAULT VALUES
GO
EXEC sp_trace_setstatus 3, 0
EXEC sp_trace_setstatus 3, 2
GO
ट्रेस फ़ाइल खोलें और आपको निम्नलिखित पता लगाना चाहिए:
लिया ताले का क्रम है:
- आशय-विशेष ताला MyTable पर
- इंटेंट-एक्सक्लूसिव लॉक पेज 1: 211 पर
- मान डाला जा रहा है के लिए क्लस्टर इंडेक्स प्रविष्टि पर RangeInsert-NullResource
- कुंजी पर विशेष ताला
ताले तब रिवर्स ऑर्डर में जारी किए जाते हैं। किसी भी बिंदु पर मेज पर एक विशेष ताला नहीं लगाया गया है।
लेकिन यह सिर्फ एक बैच डालने है! यही नहीं दो, तीन या दर्जनों समानांतर में चल रहे हैं।
हाँ यही है। SQL सर्वर (और यकीनन किसी भी संबंधपरक डेटाबेस इंजन) के पास कोई दूरदर्शिता नहीं है कि जब कोई कथन और / या बैच संसाधित करता है तो अन्य बैच क्या हो सकते हैं, इसलिए लॉक अधिग्रहण का क्रम भिन्न नहीं होता है।
उच्च अलगाव के स्तर के बारे में क्या है?
इस विशेष उदाहरण के लिए ठीक उसी ताले को लिया जाता है। मुझ पर भरोसा मत करो, यह कोशिश करो!