जैसा कि आपने निश्चित रूप से कहीं और सुना है, SQL सर्वर 2012 अंततः विस्तारित ईवेंट का एक संस्करण प्रदान करता है जो बेहतर प्रदर्शन और ईवेंट समानता दोनों के संदर्भ में SQL ट्रेस का एक व्यवहार्य विकल्प है। प्रबंधन स्टूडियो में उपयोग करने योग्य UI जैसे अन्य संवर्द्धन हैं - पहले इसके लिए आपकी एकमात्र आशा जोनाथन केहैयस के विस्तारित ईवेंट प्रबंधक थे। अनुमतियों से संबंधित एक बड़ा परिवर्तन भी है:SQL सर्वर 2012 में आपको केवल ALTER ANY EVENT SESSION
की आवश्यकता है विस्तारित ईवेंट सत्र बनाने और प्रबंधित करने के लिए (पहले आपको CONTROL SERVER
. की आवश्यकता थी )।
मुझे हाल ही में एक अधिक सूक्ष्म व्यवहार परिवर्तन दिखाई दिया जिससे ऐसा लगा कि मेरा ईवेंट सत्र ईवेंट छोड़ रहा है। परिवर्तन अपने आप में एक रहस्य नहीं है, और वास्तव में इस परिवर्तन के बारे में कई बार पढ़ने या सुनने के बाद भी (जोनाथन ने मुझे याद दिलाया कि उसने मुझे इस परिवर्तन के बारे में भी बताया था), मैं अभी भी इसे अपनी प्रारंभिक समस्या निवारण में चूक गया था, क्योंकि उस समय, यह ऐसा परिवर्तन नहीं था जो मुझे लगा कि मुझ पर प्रभाव डालेगा। देखो और देखो…
TL;DR संस्करण
SQL सर्वर 2012 में, आपका ईवेंट सत्र डिफ़ॉल्ट रूप से केवल 1,000 ईवेंट कैप्चर करेगा यदि वह ring_buffer
का उपयोग करता है लक्ष्य (और pair_matching
. के लिए 10,000 ) यह 2008/2008 R2 से एक बदलाव है, जहां यह केवल स्मृति द्वारा सीमित था। (परिवर्तन का उल्लेख लगभग एक फुटनोट में किया गया है, जुलाई 2011 में।) डिफ़ॉल्ट को ओवरराइड करने के लिए, आप MAX_EVENTS_LIMIT
का उपयोग कर सकते हैं सेटिंग - लेकिन ध्यान दें कि इस सेटिंग को SQL Server 2008/2008 R2 द्वारा पहचाना नहीं जाएगा, इसलिए यदि आपके पास कोड है जिसे कई संस्करणों के विरुद्ध काम करने की आवश्यकता है, तो आपको एक सशर्त उपयोग करने की आवश्यकता होगी।
अधिक विवरण
जिस परिदृश्य में मैं काम कर रहा था, वह इससे कहीं अधिक जटिल था, लेकिन इस मुद्दे को प्रदर्शित करने के लिए, आइए विस्तारित घटनाओं के लिए एक बहुत ही सरल उपयोग के मामले की कल्पना करें:वस्तुओं को संशोधित करने वाले पर नज़र रखना। इसके लिए एक आसान सुविधा है:object_altered
. हम इस घटना का विवरण निम्नलिखित क्वेरी से देख सकते हैं:
SELECT description FROM sys.dm_xe_objects WHERE name = 'object_altered';तब होता है जब किसी वस्तु को ALTER कथन द्वारा बदल दिया गया था। प्रत्येक ALTER ऑपरेशन के लिए यह ईवेंट दो बार उठाया जाता है। घटना तब उठाई जाती है जब ऑपरेशन शुरू होता है और जब ऑपरेशन या तो वापस ले लिया जाता है या प्रतिबद्ध होता है। इस घटना में nt_username या server_principal_name क्रियाएँ जोड़ें ताकि यह निर्धारित किया जा सके कि वस्तु को किसने बदला।
इसलिए, यदि कोई वस्तु संशोधित की जाती है, तो कहें, 20 बार, मैं 40 घटनाओं को खींचने की अपेक्षा करता हूं। और ठीक यही SQL Server 2008, 2008 R2 और 2012 में होता है। चुनौती तब आती है जब 500 से अधिक संशोधन होते हैं (1,000 से अधिक घटनाओं के लिए अग्रणी)। SQL Server 2008 और 2008 R2 में, हम अभी भी सभी ईवेंट कैप्चर करते हैं। लेकिन ring_buffer
. में बदलाव के कारण SQL Server 2012 में कुछ गिरावट आएगी लक्ष्य। प्रदर्शित करने के लिए, आइए एक त्वरित, नमूना घटना सत्र का निर्माण करें जो घटनाओं को खोने की रोकथाम के लिए प्रदर्शन करता है (ध्यान दें कि यह उन विकल्पों का सेट नहीं है जिन्हें मैं किसी भी उत्पादन प्रणाली के लिए निर्धारित करूंगा):
USE master; GO CREATE EVENT SESSION [XE_Alter] ON SERVER ADD EVENT sqlserver.object_altered ( ACTION (sqlserver.server_principal_name) WHERE (sqlserver.session_id = 78) -- change 78 to your current spid ) ADD TARGET package0.ring_buffer (SET MAX_MEMORY = 4096) WITH (EVENT_RETENTION_MODE = NO_EVENT_LOSS, MAX_DISPATCH_LATENCY = 5 SECONDS); ALTER EVENT SESSION [XE_Alter] ON SERVER STATE = START; GO
सत्र शुरू होने के साथ, उसी विंडो में, निम्न स्क्रिप्ट चलाएँ, जो दो प्रक्रियाओं को बनाता है, और उन्हें एक लूप में बदल देता है।
CREATE PROCEDURE dbo.foo_x AS SELECT 1; GO CREATE PROCEDURE dbo.foo_y AS SELECT 1; GO ALTER PROCEDURE dbo.foo_x AS SELECT 2; GO 275 ALTER PROCEDURE dbo.foo_y AS SELECT 2; GO 275 DROP PROCEDURE dbo.foo_x, dbo.foo_y; GO
अब, ऑब्जेक्ट का नाम खींचते हैं, और लक्ष्य से प्रत्येक ऑब्जेक्ट को कितनी बार संशोधित किया गया था, और ईवेंट सत्र को छोड़ दें (धैर्य रखें; मेरे सिस्टम पर, इसमें लगातार लगभग 40 सेकंड लगते हैं):
;WITH raw_data(t) AS ( SELECT CONVERT(XML, target_data) FROM sys.dm_xe_sessions AS s INNER JOIN sys.dm_xe_session_targets AS st ON s.[address] = st.event_session_address WHERE s.name = 'XE_Alter' AND st.target_name = 'ring_buffer' ), xml_data (ed) AS ( SELECT e.query('.') FROM raw_data CROSS APPLY t.nodes('RingBufferTarget/event') AS x(e) ) SELECT [object_name] = obj, event_count = COUNT(*) FROM ( SELECT --[login] = ed.value('(event/action[@name="server_principal_name"]/value)[1]', 'nvarchar(128)'), obj = ed.value('(event/data[@name="object_name"]/value)[1]', 'nvarchar(128)'), phase = ed.value('(event/data[@name="ddl_phase"]/text)[1]', 'nvarchar(128)') FROM xml_data ) AS x WHERE phase = 'Commit' GROUP BY obj; GO DROP EVENT SESSION [XE_Alter] ON SERVER; GO
परिणाम (जो Commit
. पर ध्यान केंद्रित करते हुए, कैप्चर की गई 1,000 घटनाओं में से ठीक आधे को अनदेखा कर देते हैं केवल इवेंट):
====================
foo_x 225
foo_y 275
इससे पता चलता है कि foo_x
. के लिए 50 कमिट इवेंट (कुल 100 इवेंट) को हटा दिया गया था , और ठीक 1,000 कुल ईवेंट एकत्र किए गए हैं ((225 + 275) * 2))। SQL सर्वर मनमाने ढंग से तय करता है कि किन घटनाओं को छोड़ना है - सिद्धांत रूप में, यदि यह 1,000 ईवेंट एकत्र कर रहा था और फिर रुक रहा था, तो मेरे पास foo_x
के लिए 275 ईवेंट होने चाहिए। , और 225 foo_y
. के लिए , चूंकि मैंने foo_x
. को बदल दिया है पहले, और मुझे उस लूप के पूरा होने तक टोपी को हिट नहीं करना चाहिए था। लेकिन जाहिर है कि यहां कुछ अन्य मैकेनिक्स भी हैं जो XEvents तय करते हैं कि कौन सी घटनाओं को रखना है और कौन सी घटनाओं को फेंकना है।
किसी भी स्थिति में, आप MAX_EVENTS_LIMIT
के लिए एक भिन्न मान निर्दिष्ट करके इससे निजात पा सकते हैं ADD TARGET
. में कोड का हिस्सा:
-- ... ADD TARGET package0.ring_buffer (SET MAX_MEMORY = 4096, MAX_EVENTS_LIMIT = 0) ------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^ -- ...
ध्यान दें कि 0 =असीमित, लेकिन आप कोई भी पूर्णांक मान निर्दिष्ट कर सकते हैं। जब हम नई सेटिंग के साथ ऊपर अपना परीक्षण चलाते हैं, तो हमें अधिक सटीक परिणाम दिखाई देते हैं, क्योंकि कोई भी ईवेंट नहीं छोड़ा गया था:
object_name event_count====================
foo_x 275
foo_y 275
जैसा कि ऊपर उल्लेख किया गया है, यदि आप SQL Server 2008/2008 R2 के विरुद्ध ईवेंट सत्र बनाते समय इस गुण का उपयोग करने का प्रयास करते हैं, तो आपको यह त्रुटि मिलेगी:
संदेश 25629, स्तर 16, राज्य 1, पंक्ति 1लक्ष्य के लिए, "package0.ring_buffer", अनुकूलन योग्य विशेषता, "MAX_EVENTS_LIMIT", मौजूद नहीं है।
इसलिए यदि आप किसी भी प्रकार का कोड जनरेशन कर रहे हैं और सभी संस्करणों में एक समान व्यवहार चाहते हैं, तो आपको पहले संस्करण की जांच करनी होगी, और केवल 2012 और उसके बाद के संस्करण के लिए विशेषता शामिल करनी होगी।
निष्कर्ष
यदि आप SQL Server 2008/2008 R2 से 2012 में अपग्रेड कर रहे हैं, या आपने विस्तृत ईवेंट कोड लिखा है जो कई संस्करणों को लक्षित करता है, तो आपको इस व्यवहार परिवर्तन और तदनुसार कोड के बारे में पता होना चाहिए। अन्यथा आप घटनाओं को छोड़ने का जोखिम उठाते हैं, यहां तक कि उन स्थितियों में भी जहां आप मान लेंगे - और जहां पिछले व्यवहार का अर्थ होगा - कि गिराई गई घटनाएं संभव नहीं थीं। अपग्रेड एडवाइजर या बेस्ट प्रैक्टिस एनालाइजर जैसे टूल आपके लिए इस बारे में कुछ नहीं बता रहे हैं।
इस समस्या के आसपास के तंत्र को इस बग रिपोर्ट और इस ब्लॉग पोस्ट में विस्तार से वर्णित किया गया है।