स्थापना IDENTITY_INSERT ON
अपने आप पर संगामिति को समाप्त नहीं करता है - यह मेज पर कोई विशेष ताले नहीं रखता है, केवल एक संक्षिप्त स्कीमा स्थिरता (SCH-S) लॉक है।
तो सैद्धांतिक रूप से क्या हो सकता है, डिफ़ॉल्ट व्यवहार के तहत, क्या आप इसे सत्र 1 में कर सकते हैं:
BEGIN TRANSACTION;
-- 1
SET IDENTITY_INSERT dbo.tablename ON;
-- 2
INSERT dbo.tablename(id, etc) VALUES(100, 'foo'); -- next identity is now 101
-- 3
INSERT dbo.tablename(id, etc) VALUES(101, 'foo'); -- next identity is now 102
-- 4
SET IDENTITY_INSERT dbo.tablename OFF;
COMMIT TRANSACTION;
एक और सत्र में, आप तालिका 1, 2, 3 या 4 में पंक्तियों को सम्मिलित कर सकते हैं। यह एक अच्छी बात की तरह लग सकता है , सिवाय इसके कि 2 और 3 के बीच होने वाले किसी भी आवेषण के लिए क्या होता है, यह स्वतः उत्पन्न मूल्य ट्रिगर होता है एक और सत्र द्वारा कथन 2 के परिणामों पर आधारित है - इसलिए यह एक 101 उत्पन्न करेगा, और फिर कथन 3 प्राथमिक कुंजी उल्लंघन के साथ विफल हो जाएगा। यह कुछ WAITFOR
एस के साथ खुद को स्थापित करने और परीक्षण करने के लिए बहुत सरल है :
-- session 1
-- DROP TABLE dbo.what;
CREATE TABLE dbo.what(id INT IDENTITY PRIMARY KEY);
GO
BEGIN TRANSACTION;
SET IDENTITY_INSERT dbo.what ON;
INSERT dbo.what(id) VALUES(32);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(33);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(34);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(35);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(36);
SET IDENTITY_INSERT dbo.what OFF;
COMMIT TRANSACTION;
एक बार जब वह बैच शुरू हो गया, तो इस बैच को दूसरी विंडो में शुरू करें:
-- session 2
INSERT dbo.what DEFAULT VALUES;
WAITFOR DELAY '00:00:01';
GO 20
सत्र 2 में केवल 1-20 से ही मान डालना चाहिए, है ना? सिवाय इसके कि अंतर्निहित पहचान आपके मैनुअल आवेषण सत्र 1 द्वारा अपडेट की गई है, कुछ बिंदु पर सत्र 2 उठाएगा जहां सत्र 1 छोड़ दिया गया है, और 32, या 33, या 34 आदि सम्मिलित करें। इसे ऐसा करने की अनुमति दी जाएगी, लेकिन तब सत्र 1 पीके उल्लंघन के साथ अगले प्रविष्टि पर विफल हो जाएगा (जो एक जीत सिर्फ समय की बात हो सकती है)।
वर्कअराउंड करने का एक तरीका यह है TABLOCK
कि पहले इंसर्ट पर इनवॉइस करें:
INSERT dbo.what WITH (TABLOCK) (id) VALUES(32);
यह किसी भी अन्य उपयोगकर्ताओं को इस तालिका के साथ सम्मिलित करने (या वास्तव में कुछ भी करने) का प्रयास करेगा, जब तक कि आप उन संग्रहीत पंक्तियों को वापस नहीं ले जाते। यह संक्षिप्तता को सुनिश्चित करता है, लेकिन यह वैसा ही है जैसा आप चाहते हैं काम करने के लिए अवरुद्ध हैं। और उम्मीद है कि यह कुछ ऐसा नहीं है जो इतनी लगातार दर पर हो रहा है जहां आप हर समय अन्य लोगों को रोक रहे हैं।
अन्य वर्कअराउंड के एक जोड़े:
IDENTITY
उत्पन्न मूल्य के बारे में देखभाल करना बंद करें । किसे पड़ी है? मूल मान बहुत महत्वपूर्ण UNIQUEIDENTIFIER
होने पर (शायद एक अलग तालिका IDENTITY
में एक सरोगेट के रूप में उत्पन्न) का उपयोग करें ।
- एक "सॉफ्ट डिलीट" का उपयोग करने के लिए संग्रह प्रक्रिया को बदलें जहां कुछ शुरू में संग्रहीत के रूप में चिह्नित किया जाता है और अभिलेखीय को कुछ बाद की तारीख तक स्थायी नहीं बनाया जाता है। फिर जो भी प्रक्रिया उन्हें वापस ले जाने की कोशिश कर रही है वह बस एक सीधा अपडेट कर सकती है और सॉफ्ट डिलीट फ्लैग को ठीक कर सकती है।