[ Част 1 | Част 2 | Част 3 ]
В част 1 от тази серия обясних как стигнах до заключението, че трябва да деактивираме проследяването по подразбиране. В част 2 показах сесията с разширени събития, която разгърнах, за да заснема всички събития за промяна на размера на файла. В тази публикация искам да покажа изгледите, които създадох, за да улесня използването на данните за събитията за хората, както и да обясня някои предупреждения.
Смилаеми изгледи
Първо, създадох изглед, който ще разкрие важните битове от данните за сесията на разширени събития и ще го постави в базата данни на помощната програма, която съществува във всеки екземпляр:
CREATE VIEW dbo.vwFileSizeChanges AS WITH FileInfo(XEPath) AS ( SELECT LEFT(BasePath,COALESCE(NULLIF(CHARINDEX(SessName,BasePath)-1,-1),0)) + SessName + N'*.xel' FROM ( SELECT xmlsrc.data.value(N'(@name)[1]', N'nvarchar(max)'), SessName 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, SessName) CROSS APPLY TargetData.nodes(N'//EventFileTarget/File') AS xmlsrc(data) ) AS InnerData(BasePath, SessName) ), 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') --, [EventData] -- raw XML to troubleshoot specific events FROM SessionData CROSS APPLY EventData.nodes('/event') AS x(d) ) SELECT DatabaseName = DB_NAME(DatabaseID), [FileName], DurationSeconds = CONVERT(decimal(18,3),Duration/1000000.0), StartTimeUTC = CONVERT(datetime2(3), DATEADD(MICROSECOND, -Duration, EndTimeUTC)), EndTimeUTC = CONVERT(datetime2(3), EndTimeUTC), FileType, Culprit = CASE WHEN Culprit IS NULL AND AppName LIKE N'Repl%' THEN AppName ELSE Culprit END, 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--, [EventData] -- raw XML to troubleshoot specific events FROM src;
Сега, когато някой иска да прегледа последните събития за промяна на размера на файла на който и да е сървър, той изпълнява:
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges ORDER BY StartTimeUTC DESC;
Когато деактивирате проследяването по подразбиране, файловете за проследяване не се изтриват, така че всички събития от преди тази промяна все още могат да бъдат прегледани. Мога да взема назаем от факта, че следата по подразбиране е твърдо кодирана към същия път като SERVERPROPERTY(N'ErrorLogFileName')
и създайте втори изглед, който обединява горните данни с повече данни от трасирането по подразбиране:
CREATE VIEW dbo.vwFileSizeChanges_IncludingTrace AS 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) -- arbitrary date range to support DST conversions going a year+ each way -- will add 2022, 2023, etc. later (if DST is still a thing then) ),vars(TracePath) AS ( SELECT 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 t.DatabaseName, t.[FileName], DurationSeconds = CONVERT(decimal(18,3), t.Duration/1000000.0), StartTimeUTC = CONVERT(datetime2(3), DATEADD(MINUTE, COALESCE(st1.d,0), t.StartTime)), EndTimeUTC = CONVERT(datetime2(3), DATEADD(MINUTE, COALESCE(st2.d,0), t.EndTime)), FileType = CASE WHEN t.EventClass IN (92, 94) THEN 'Data' WHEN t.EventClass IN (93, 95) THEN 'Log' END, Culprit = CASE WHEN t.TextData IS NULL AND t. ApplicationName LIKE N'Repl%' THEN t.ApplicationName ELSE t.TextData END, IsAutomatic = 'true', ChangeMB = CONVERT(bigint, t.IntegerData)*8/1024, Principal = t.LoginName, t.HostName, App = CASE WHEN t.ApplicationName LIKE N'%Management Studio%Query%' THEN N'SSMS - Query Window' WHEN t.ApplicationName LIKE N'%Management Studio%' THEN N'SSMS - GUI!' ELSE t.ApplicationName END --, [EventData] = CONVERT(xml, NULL) FROM vars CROSS APPLY sys.fn_trace_gettable(vars.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 src='trace', * FROM trc UNION ALL SELECT src='xe', * FROM dbo.vwFileSizeChanges;
Този изглед настройва данните за проследяване (заснети по източно време на всички наши сървъри) към UTC и обработва DST, където е подходящо. Ако данните попадат извън обхвата на CTE, наречен dst
, вместо това ще бъде изразено в източно време (и можете лесно да коригирате това, като добавите повече DST диапазони). Има допълнителна колона, наречена src
така че можете да заявите старите данни за проследяване, като използвате:
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges_IncludingTrace WHERE src = 'trace' ORDER BY StartTimeUTC DESC;
Предупреждения
Няма такова нещо като безплатен обяд! Въпреки че съм убеден, че премахването на проследяването по подразбиране ще има нулево или, много по-вероятно, положително въздействие върху нашите работни натоварвания, има някои неща, които трябва да имате предвид за вашата среда, ако решите да следвате моя път:
- Базите данни не са постоянни
В моята дефиниция на сесията на разширени събития избрах да не прилагам
collect_database_name
, а в изгледа по-горе можете да видите, че разрешавам това по време на изпълнение с помощта наDB_NAME(database_id)
. Тук има риск, че някой може да създаде база данни, да извърши куп дейности, които създават прехвърляне на файлове и разбиване на диск, след което да изхвърли базата данни.database_id
изложени в XML вече няма смисъл в този случай иDB_NAME()
ще върнеNULL
.Избрах този резултат, вместо да разчитам единствено на името на базата данни, тъй като горната верига от събития е много по-малко вероятна от преименуването на база данни (където
database_id
ще остане същото). В този случай може да търсите събития, случили се с база данни, но да търсите с грешно (текущо) име, в зависимост от това кога са се случили събитията.Ако искате да можете да използвате едното или другото, можете да използвате следната дефиниция на сесията:
... ADD EVENT sqlserver.database_file_size_change ( SET collect_database_name = (1) ACTION ( sqlserver.sql_text, ...
Това също не може да бъде безплатно или би се случило по подразбиране, но ще призная, че никога не съм тествал ефекта от добавянето му към колекцията.
- Отчетите за SSMS ще бъдат малко по-малко надеждни
Страничен ефект от деактивирането на проследяването по подразбиране е нарушаване на някои от „Стандартните отчети“ на Management Studio. Анкетирах нашите екипи, преди да направя това, и вие ще искате да направите същото, за да сте сигурни, че потребителите ви не разчитат на нито едно от тях. Също така ще искате да им напомните, че на отчетите в момента не може да се разчита така или иначе, поради същата причина, поради която аз не мога да разчитам директно на проследяването по подразбиране – те могат да изтеглят само данни, които все още са в трасето. Празен отчет не означава непременно, че не са се случили събития; това може да означава, че информацията вече не е налична. Ако екипът наистина иска да използва тази информация, бих могъл да се уверя, че е надеждна, като им изпращам персонализирани отчети, които използват по-надежден източник.
Следните отчети са тези, които виждам да извличат поне част от информацията си от проследяването по подразбиране и защо не се нуждаем от отчетите, дори ако може да им се вярва:
История на промените в схемата Вече имаме контрол на източника, строг процес на преглед/внедряване и DDL тригери, които улавят информация за промените в схемата. История на промените в конфигурацията
и
Консумация на паметНашият инструмент за наблюдение ни казва за промените в конфигурацията на ниво екземпляр, така че този отчет в SSMS е излишен. Неуспехи при влизане Те са в регистъра на грешките (и в инструмента за преглед на събития), тъй като по стандарт ние активираме одит „Само неуспешни влизания“ за всички екземпляри на SQL Server. Някои сървъри също имат допълнителен официален одит от съображения за съответствие. Използване на диск Наред с друга информация, това изброява събитията за автоматично нарастване и автоматично свиване от проследяването по подразбиране, които сега улавяме с помощта на разширени събития. Архивиране и възстановяване на събития Тази информация е лесно достъпна в msdb.dbo.backupset, ако някога се нуждаем от нея, но тя също е включена в нашата автоматизация около архивиране и възстановяване (никога не разглеждаме проследяването по подразбиране за тази информация).
История на съгласуваност на базата данни Както при архивирането, ние имаме автоматизация, изградена около DBCC CHECKDB; ако някой излезе извън това и стартира нещо ръчно, то пак ще се покаже в регистъра за грешки. И имаме много повече контрол върху това колко дълго съхраняваме регистрационни файлове за грешки и колко често ги рециклираме. Рециклираме всяка вечер, за да е по-лесно да намерим събитие, за което подозираме, че се е случило в даден ден в миналото.
Заключение
Това беше забавен, но сложен проект и аз съм доволен от резултата досега. Благодаря, че карате заедно!
[ Част 1 | Част 2 | Част 3 ]