[ भाग 1 | भाग 2 | भाग 3 ]
इस श्रृंखला की पहली पोस्ट में, मैंने वह विश्लेषण दिखाया जिसका उपयोग मैंने यह निर्धारित करने के लिए किया था कि डिफ़ॉल्ट ट्रेस हमारे लिए नहीं है। यह देखते हुए कि हमें वास्तव में इसके स्थान पर कौन सी जानकारी एकत्र करने की आवश्यकता है (फ़ाइल आकार में परिवर्तन), और इसे उपयोगकर्ताओं के सामने कैसे लाया जाना चाहिए, मैंने डिफ़ॉल्ट ट्रेस के बारे में निम्नलिखित बिंदुओं पर विचार किया:
- यह केवल स्वचालित को कैप्चर करता है आयोजन;
- यह घटना का कारण बनने वाले "अपराधी" बैच को कैप्चर नहीं करता है, जब तक कि आप पर्याप्त भाग्यशाली न हों कि इसे किसी अन्य कारण से भी कैप्चर किया गया था (उदाहरण के लिए डीडीएल); और,
- यह स्थानीय समय का उपयोग करके घटनाओं को कैप्चर करता है (हमारे सर्वर पूर्वी हैं और डीएसटी का पालन करते हैं)।
अपने बचाव में, यह उन स्वचालित घटनाओं के बारे में बहुत सारी महत्वपूर्ण जानकारी प्राप्त करता है। डिफ़ॉल्ट ट्रेस को अक्षम करने के बाद, हम अभी भी उन घटनाओं की समीक्षा करना चाहेंगे जो परिवर्तन से पहले हुई थीं और उन फ़ाइलों में कैप्चर की गई थीं। लेकिन एक बार डिफ़ॉल्ट ट्रेस अक्षम हो जाने के बाद, पंक्ति अब sys.traces
. में मौजूद नहीं रहती है , इसलिए आप .trc
. का पथ निर्धारित नहीं कर सकते वहां से फाइलें। यहाँ वह जगह है जहाँ डिफ़ॉल्ट ट्रेस की अनम्यता वास्तव में एक लाभ प्रदान करती है:फ़ाइलों को उसी फ़ोल्डर में रहने के लिए हार्डकोड किया जाता है जैसे SERVERPROPERTY(N'ErrorLogFileName')
. इसलिए, भले ही डिफ़ॉल्ट ट्रेस अक्षम हो, फिर भी हम निम्न क्वेरी (UTC में डेटा दिखाने के लिए समायोजन के साथ) का उपयोग करके फ़ाइलों से डेटा खींच सकते हैं:
;WITH dst AS ( SELECT s,e,d FROM (VALUES ('20190310','20191103',240),('20191103','20200308',300), ('20200308','20201101',240),('20201101','20210314',300), ('20210314','20211107',240)) AS dst(s,e,d) ), -- will add 2022, 2023, etc. later (if DST is still a thing then) p AS ( SELECT TracePath = REVERSE(SUBSTRING(p, CHARINDEX(N'\', p), 260)) + N'log.trc' FROM (SELECT REVERSE((CONVERT(nvarchar(max), SERVERPROPERTY(N'ErrorLogFileName'))))) AS s(p) ), trc AS ( SELECT src = 'trc', t.DatabaseName, t.[FileName], DurationSeconds = CONVERT(decimal(18,3),Duration/1000000.0), StartTimeUTC = DATEADD(MINUTE, COALESCE(st1.d,0), t.StartTime), EndTimeUTC = DATEADD(MINUTE, COALESCE(st2.d,0), t.EndTime), FileType = CASE t.EventClass WHEN 92 THEN 'Data' WHEN 93 THEN 'Log' END, Culprit = TextData, IsAutomatic = 'true', ChangeMB = CONVERT(bigint, IntegerData)*8/1024, Principal = t.LoginName, t.HostName, App = CASE WHEN ApplicationName LIKE N'%Management Studio%Query%' THEN N'SSMS - Query Window' WHEN ApplicationName LIKE N'%Management Studio%' THEN N'SSMS - GUI!' ELSE ApplicationName END FROM p CROSS APPLY sys.fn_trace_gettable(p.TracePath, DEFAULT) AS t LEFT OUTER JOIN dst AS st1 ON t.StartTime >= DATEADD(HOUR,2,st1.s) AND t.StartTime < DATEADD(HOUR,2,st1.e) LEFT OUTER JOIN dst AS st2 ON t.EndTime >= DATEADD(HOUR,2,st2.s) AND t.EndTime < DATEADD(HOUR,2,st2.e) WHERE t.EventClass IN (92,93) ) SELECT * FROM trc ORDER BY StartTimeUTC DESC;
एक सर्वर से नमूना परिणाम, जहां निश्चित रूप से कुछ मैन्युअल और स्वचालित घटनाएं हुईं (विस्तार करने के लिए क्लिक करें):
प्रतिस्थापन लिखना
इसे बदलने के लिए मैंने जो विस्तारित ईवेंट सत्र तैयार किया है, जो मैन्युअल फ़ाइल आकार परिवर्तन और स्वचालित ईवेंट का कारण बनने वाले क्वेरी टेक्स्ट को भी कैप्चर करेगा, इस प्रकार है:
CREATE EVENT SESSION FileSizeChanges ON SERVER ADD EVENT sqlserver.database_file_size_change ( ACTION ( sqlserver.sql_text, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.username, sqlserver.server_principal_name ) ) ADD TARGET package0.event_file ( SET filename = N'W:\SomePath\FileSizeChanges.xel', MAX_FILE_SIZE = 100, -- MB MAX_ROLLOVER_FILES = 100 -- 100 MB x 100 = max 10 GB ) WITH ( MAX_MEMORY = 8192 KB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY = 30 SECONDS, MAX_EVENT_SIZE = 0 KB, TRACK_CAUSALITY = OFF, STARTUP_STATE = ON ); ALTER EVENT SESSION FileSizeChanges ON SERVER STATE = START;
जबकि यह username
जैसा दिखता है और server_principal_name
अनावश्यक हो सकता है, मुझे वास्तव में ऐसे मामले मिले जहां बाद वाले NULL
. थे (और ऐसा लगता है कि यह समस्या कुछ समय से है)।
परिणाम जांचा जा रहा है
मैंने उस सत्र को 22 फरवरी को सक्षम किया था, इसलिए इसमें 12 तारीख को कैप्चर किए गए डिफ़ॉल्ट ट्रेस की घटनाएँ गायब हैं, लेकिन इसने 23 तारीख से एकल ऑटोग्रोथ घटना से अधिक पर कब्जा कर लिया। ऊपर के समान आकार का परिणाम प्राप्त करने के लिए मैंने निम्नलिखित क्वेरी चलाई:
;WITH FileInfo(XEPath) AS ( SELECT LEFT(BasePath,COALESCE(NULLIF(CHARINDEX(SessionName,BasePath)-1,-1),0)) + SessionName + N'*.xel' FROM ( SELECT xmlsrc.data.value(N'(@name)[1]', N'nvarchar(max)'), SessionName FROM ( SELECT CONVERT(xml,target_data), s.[name] FROM sys.dm_xe_session_targets AS t INNER JOIN sys.dm_xe_sessions AS s ON s.[address] = t.event_session_address WHERE s.[name] = N'FileSizeChanges' ) AS xefile (TargetData, SessionName) CROSS APPLY TargetData.nodes(N'//EventFileTarget/File') AS xmlsrc(data) ) AS InnerData(BasePath, SessionName) ), SessionData(EventData) AS ( SELECT CONVERT(xml, TargetData.event_data) FROM FileInfo CROSS APPLY sys.fn_xe_file_target_read_file(FileInfo.XEPath, NULL, NULL, NULL) AS TargetData ), src AS ( SELECT EndTimeUTC = x.d.value(N'(@timestamp)[1]', N'datetime2'), DatabaseID = x.d.value(N'(data [@name="database_id"]/value)[1]', N'int'), [FileName] = x.d.value(N'(data [@name="file_name"]/value)[1]', N'sysname'), Duration = x.d.value(N'(data [@name="duration"]/value)[1]', N'int'), FileType = x.d.value(N'(data [@name="file_type"]/text)[1]', N'varchar(4)'), Culprit = x.d.value(N'(action[@name="sql_text"]/value)[1]', N'nvarchar(max)'), IsAutomatic = x.d.value(N'(data [@name="is_automatic"]/value)[1]', N'varchar(5)'), ChangeKB = x.d.value(N'(data [@name="size_change_kb"]/value)[1]', N'bigint'), Principal = x.d.value(N'(action[@name="server_principal_name"]/value)[1]', N'sysname'), username = x.d.value(N'(action[@name="username"]/value)[1]', N'sysname'), AppName = x.d.value(N'(action[@name="client_app_name"]/value)[1]', N'sysname'), HostName = x.d.value(N'(action[@name="client_hostname"]/value)[1]', N'sysname') FROM SessionData CROSS APPLY EventData.nodes(N'/event') AS x(d) ) SELECT src = 'xe', DatabaseName = DB_NAME(DatabaseID), [FileName], DurationSeconds = CONVERT(decimal(18,3), Duration/1000000.0), StartTimeUTC = DATEADD(MICROSECOND, -Duration, EndTimeUTC), EndTimeUTC, FileType, Culprit, IsAutomatic, ChangeMB = CONVERT(decimal(18,3), ChangeKB / 1024.0), Principal = COALESCE([Principal], COALESCE(NULLIF(username,N''), N'?')), HostName, App = CASE WHEN AppName LIKE N'%Management Studio%Query%' THEN N'SSMS - Query Window' WHEN AppName LIKE N'%Management Studio%' THEN N'SSMS - GUI!' ELSE AppName END FROM src ORDER BY StartTimeUTC DESC;
परिणाम मुझे अतिरिक्त मज़ा दिखाते हैं, जिसमें (हांफना!) UI से "डेटाबेस को सिकोड़ें" कार्य चलाना शामिल है (विस्तार करने के लिए क्लिक करें):
इसे हर जगह परिनियोजित करना
विश्वास है कि अब मुझे किसी भी सर्वर पर फ़ाइल आकार परिवर्तन की घटनाओं की एक और पूरी तस्वीर मिल सकती है, यह तैनाती का समय था। मैंने पहले हर जगह डिफ़ॉल्ट ट्रेस को अक्षम करने के लिए एक CMS क्वेरी विंडो का उपयोग किया, और show advanced options
सेट किया जिस तरह से मैंने इसे पाया:
IF EXISTS ( SELECT 1 FROM sys.configurations WHERE name = N'default trace enabled' AND value_in_use = 1 ) BEGIN DECLARE @OriginalAdvancedOptions bit = ( SELECT CONVERT(bit, value_in_use) FROM sys.configurations WHERE name = N'show advanced options' ); IF @OriginalAdvancedOptions = 0 -- need to turn this on if it's not already BEGIN EXEC sys.sp_configure @configname = N'show advanced options', @configvalue = 1; RECONFIGURE WITH OVERRIDE; END EXEC sys.sp_configure @configname = N'default trace enabled', @configvalue = 0; IF @OriginalAdvancedOptions = 0 -- need to set it back (else leave it) BEGIN EXEC sys.sp_configure @configname = N'show advanced options', @configvalue = 0; END RECONFIGURE WITH OVERRIDE; END GO
फिर, विस्तारित ईवेंट सत्र बनाने के लिए, मुझे डायनेमिक SQL का उपयोग करने की आवश्यकता है, क्योंकि कुछ सर्वरों में SERVERPROPERTY(N'ErrorLogFileName')
के लिए अलग-अलग पथ हो सकते हैं। और उस तर्क को पैरामीटरयुक्त नहीं किया जा सकता है।
DECLARE @path nvarchar(max) = (SELECT REVERSE(SUBSTRING(p, CHARINDEX(N'\', p), 4000)) FROM (SELECT REVERSE((CONVERT(nvarchar(max), SERVERPROPERTY(N'ErrorLogFileName'))))) AS s(p)); IF EXISTS (SELECT 1 FROM sys.dm_xe_sessions WHERE name = N'FileSizeChanges') BEGIN EXEC sys.sp_executesql N'DROP EVENT SESSION FileSizeChanges ON SERVER;'; END DECLARE @sql nvarchar(max) = N' CREATE EVENT SESSION FileSizeChanges ON SERVER ADD EVENT sqlserver.database_file_size_change ( ACTION ( sqlserver.sql_text, sqlserver.client_app_name, sqlserver.client_hostname, sqlserver.username, sqlserver.server_principal_name ) ) ADD TARGET package0.event_file ( SET filename = ''' + @path + N'FileSizeChanges.xel'', MAX_FILE_SIZE = 100, -- MB MAX_ROLLOVER_FILES = 100 -- 100 MB x 100 = max 10 GB ) WITH ( MAX_MEMORY = 8192 KB, EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY = 30 SECONDS, MAX_EVENT_SIZE = 0 KB, TRACK_CAUSALITY = OFF, STARTUP_STATE = ON ); ALTER EVENT SESSION FileSizeChanges ON SERVER STATE = START;'; EXEC sys.sp_executesql @sql;
सबूत हलवा में है
मैंने एक नकली कार्यभार बनाया जो जानबूझकर उन चीजों से भारी था जो डिफ़ॉल्ट ट्रेस पर ईवेंट लॉग करेंगे, फिर इसे डिफ़ॉल्ट ट्रेस सक्षम किए बिना कई बार चलाया, यह दिखाने के लिए कि पर्यवेक्षक प्रभाव कार्यभार पर प्रभाव डाल सकता है।
SELECT [starting] = sysdatetime(); GO EXEC sys.sp_executesql N'CREATE OR ALTER PROCEDURE dbo.dostuff AS BEGIN SET NOCOUNT ON; SELECT DISTINCT TOP (1000) object_id, column_id INTO #blat FROM sys.all_columns; ALTER TABLE #blat ADD CONSTRAINT PK_wahoo PRIMARY KEY (object_id, column_id); ALTER TABLE #blat ADD CONSTRAINT DF_what DEFAULT(1) FOR object_id; CREATE INDEX IX_what ON #blat(column_id); DROP TABLE #blat; END'; EXEC dbo.dostuff; CREATE USER smidgen WITHOUT LOGIN; ALTER ROLE db_owner ADD MEMBER smidgen; DBCC TRACEON(2861) WITH NO_INFOMSGS; DBCC TRACEOFF(2861) WITH NO_INFOMSGS; DROP USER smidgen; GO 5000 SELECT [finished] = sysdatetime(); GO
औसत रनटाइम:
डिफ़ॉल्ट ट्रेस | औसत कार्यभार समय |
---|---|
सक्षम | 147.4s |
अक्षम | 131.6s |
एक 10-11% रनटाइम कमी निश्चित रूप से अलगाव में बहुत बड़ी नहीं है, लेकिन अगर आप 200+ सर्वरों के पूरे बेड़े में संचयी प्रभाव के बारे में सोचते हैं तो यह एक बड़ी जीत है।
आगे क्या है?
अभी तक ऐसा न करें . हमें अभी भी डिफ़ॉल्ट ट्रेस को अक्षम करने के कुछ दुष्प्रभावों के बारे में बात करनी है, और दृश्य बनाना है ताकि उपयोगकर्ता XQuery विशेषज्ञ बने बिना आसानी से सत्र डेटा का उपभोग कर सकें। बने रहें!
[ भाग 1 | भाग 2 | भाग 3 ]