SQL सर्वर की दुनिया में एक स्थायी मिथक है कि दोनों DROP TABLE
और TRUNCATE TABLE
आदेश गैर-लॉग हैं।
वे नहीं हैं। वे दोनों पूरी तरह से लॉग इन हैं, लेकिन कुशलता से लॉग इन हैं।
आप इसे आसानी से अपने लिए साबित कर सकते हैं। परीक्षण डेटाबेस और तालिका सेट करने के लिए निम्न कोड चलाएँ, और दिखाएँ कि हमारी तालिका में 10,000 पंक्तियाँ हैं:
CREATE DATABASE [TruncateTest]; GO ALTER DATABASE [TruncateTest] SET RECOVERY SIMPLE; GO USE [TruncateTest]; GO CREATE TABLE [TestTable] ( [c1] INT IDENTITY, [c2] CHAR (8000) DEFAULT 'a'); GO SET NOCOUNT ON; GO INSERT INTO [TestTable] DEFAULT VALUES; GO 10000 SELECT COUNT (*) AS N'RowCount' FROM [TestTable]; GO
परिणाम:
रोकाउंट————
10000
और फिर निम्न कोड, जो लेन-देन में तालिका को छोटा करता है और पंक्ति गणना की जांच करता है:
BEGIN TRAN; GO TRUNCATE TABLE [TestTable]; GO SELECT COUNT (*) AS N'RowCount' FROM [TestTable]; GO
परिणाम:
रोकाउंट————
0
अब टेबल खाली है। लेकिन मैं लेन-देन को वापस ले सकता हूं और सभी डेटा को फिर से वापस रख सकता हूं:
ROLLBACK TRAN; GO SELECT COUNT (*) AS N'RowCount' FROM [TestTable]; GO
परिणाम:
रोकाउंट————
10000
स्पष्ट रूप से TRUNCATE
ऑपरेशन लॉग होना चाहिए अन्यथा रोल बैक ऑपरेशन काम नहीं करेगा।
तो ग़लतफ़हमी कहाँ से आती है?
यह DROP
. के व्यवहार से आता है और TRUNCATE
बड़ी मेजों पर संचालन। वे लगभग तुरंत ही पूर्ण हो जाएंगे, और यदि आप fn_dblog
का उपयोग करके लेन-देन लॉग में देखते हैं ठीक बाद में, आप केवल ऑपरेशन से उत्पन्न लॉग रिकॉर्ड की एक छोटी संख्या देखेंगे। वह छोटी संख्या तालिका के आकार को छोटा या गिराए जाने से संबंधित नहीं है, इसलिए ऐसा लगता है जैसे DROP
और TRUNCATE
संचालन गैर-लॉग हैं।
लेकिन वे पूरी तरह से लॉग इन हैं, जैसा कि मैंने ऊपर दिखाया है। तो संचालन के लिए लॉग रिकॉर्ड कहाँ हैं?
इसका उत्तर यह है कि लॉग रिकॉर्ड 'डिफर्ड ड्रॉप' नामक एक तंत्र द्वारा बनाया जाएगा, बस तुरंत नहीं, जिसे SQL Server 2000 SP3 में जोड़ा गया था।
जब कोई तालिका गिरा दी जाती है या काट दी जाती है, तो तालिका के लिए आवंटित सभी डेटा फ़ाइल पृष्ठों को हटा दिया जाना चाहिए। SQL Server 2000 SP3 से पहले इसके लिए तंत्र इस प्रकार था:
तालिका में आवंटित प्रत्येक सीमा के लिएशुरू करें
सीमा पर एक विशिष्ट आवंटन लॉक प्राप्त करें
इसकी जांच करें प्रत्येक पृष्ठ के लिए पेज लॉक इस हद तक (एक्सक्लूसिव मोड में लॉक प्राप्त करें, और तुरंत इसे छोड़ दें, सुनिश्चित करें कि किसी और ने पेज लॉक नहीं किया है)
ऐसा न करें सीमा लॉक जारी करें, यह गारंटी देते हुए कि कोई और उस सीमा का उपयोग नहीं कर सकता
अगली सीमा तक ले जाएं
समाप्त करें
चूंकि ऑपरेशन के अंत तक सभी हद तक ताले रखे गए थे, और प्रत्येक लॉक में थोड़ी मात्रा में मेमोरी होती है, इसलिए लॉक मैनेजर के लिए मेमोरी से बाहर निकलना संभव था जब एक DROP
या TRUNCATE
एक बहुत बड़ी मेज का हुआ। कुछ SQL सर्वर ग्राहकों ने पाया कि वे SQL Server 2000 पर आउट-ऑफ-मेमोरी स्थितियों में भाग गए, क्योंकि टेबल बहुत बड़े हो गए और सिस्टम मेमोरी में वृद्धि को काफी हद तक पीछे छोड़ दिया।
आस्थगित-ड्रॉप तंत्र DROP
. का अनुकरण करता है या TRUNCATE
एक पृष्ठभूमि कार्य द्वारा बाद में प्रसंस्करण के लिए, तालिका के लिए आवंटन को हटाकर और उन्हें 'आस्थगित-ड्रॉप कतार' पर रखकर तुरंत ऑपरेशन पूरा करना। यह अनहुक-एंड-ट्रांसफर ऑपरेशन केवल मुट्ठी भर लॉग रिकॉर्ड बनाता है। यह वह ऑपरेशन है जो ऊपर दिए गए मेरे कोड उदाहरण में किया जा रहा है और रोल-बैक किया जा रहा है।
'डिफर्ड-ड्रॉप बैकग्राउंड टास्क' हर कुछ सेकंड में घूमता है और डिफर्ड-ड्रॉप क्यू पर सभी पेजों और विस्तार को छोटे में हटा देता है बैच, यह गारंटी देता है कि ऑपरेशन स्मृति से बाहर नहीं होगा। ये डीलोकेशन पूरी तरह से लॉग किए गए हैं, लेकिन याद रखें कि डेटा या इंडेक्स रिकॉर्ड से भरे पेज को डीलोकेट करने से उन रिकॉर्ड्स के अलग-अलग डिलीट लॉग नहीं होते हैं; इसके बजाय पूरे पृष्ठ को प्रासंगिक पीएफएस (पेज फ्री स्पेस) आवंटन बाइट-मैप में डीललोकेटेड के रूप में चिह्नित किया गया है।
SQL Server 2000 SP3 से आगे, जब आप DROP
करते हैं या TRUNCATE
तालिका में, आप केवल कुछ लॉग रिकॉर्ड जेनरेट होते हुए देखेंगे। यदि आप एक या दो मिनट प्रतीक्षा करते हैं, और फिर लेन-देन लॉग में फिर से देखते हैं, तो आप देखेंगे कि हजारों लॉग रिकॉर्ड आस्थगित-ड्रॉप ऑपरेशन द्वारा उत्पन्न किए गए हैं, प्रत्येक एक पृष्ठ या सीमा को हटा रहा है। ऑपरेशन पूरी तरह से और कुशलता से लॉग किया गया है।
हमारे द्वारा ऊपर बनाए गए परिदृश्य का उपयोग करते हुए, यहां एक उदाहरण दिया गया है:
CHECKPOINT; GO TRUNCATE TABLE [TestTable]; GO SELECT COUNT (*) AS N'LogRecCount' FROM fn_dblog (NULL, NULL); GO
परिणाम:
LogRecCount———–
25
जैसा कि आप देख सकते हैं, स्पष्ट रूप से कोई लॉग रिकॉर्ड नहीं हैं जो टेस्टटेबल तालिका में 10,000 पृष्ठों, प्लस 1,250 विस्तारों को हटाते हैं।
अगर मैं कुछ सेकंड प्रतीक्षा करता हूं, और फिर fn_dblog
चलाता हूं कोड फिर से, मुझे मिलता है:
———–
3811
आपको आश्चर्य हो सकता है कि कम से कम 10,000 लॉग रिकॉर्ड क्यों नहीं हैं - प्रत्येक पृष्ठ को हटाए जाने के लिए एक। ऐसा इसलिए है क्योंकि पेज डीललोकेशन भी कुशलता से लॉग किया गया है - एक लॉग रिकॉर्ड के साथ पीएफएस पेज में लगातार 8 डेटा फ़ाइल पेजों के लिए पीएफएस पेज आवंटन परिवर्तन को दर्शाता है, प्रत्येक डेटा फ़ाइल पेज के लिए एक लॉग रिकॉर्ड के बजाय पीएफएस पेज में इसकी आवंटन स्थिति को दर्शाता है।
वर्तमान पुनर्प्राप्ति मॉडल के आधार पर पूर्ण या न्यूनतम लॉगिंग के नियमों का पालन करते हुए SQL सर्वर हमेशा जितना संभव हो उतना कम लेनदेन लॉग उत्पन्न करने का प्रयास करता है। यदि आप अनहुक-एंड-ट्रांसफर और डिफर्ड-ड्रॉप तंत्र द्वारा उत्पन्न वास्तविक लॉग रिकॉर्ड को देखना चाहते हैं, तो बस उपरोक्त fn_dblog कोड में COUNT (*) के लिए * स्थानापन्न करें और लेन-देन नाम के साथ लेनदेन की तलाश करें DeferredAllocUnitDrop::Process
।
भविष्य की पोस्ट में मैं उन इंटर्नल पर चर्चा करूंगा जो SQL सर्वर स्टोरेज इंजन के प्रदर्शन पहलुओं के आसपास अन्य लगातार मिथकों को रेखांकित करते हैं।