[ Bagian 1 | Bagian 2 | Bagian 3 ]
Di bagian 1 seri ini, saya menjelaskan bagaimana saya sampai pada kesimpulan bahwa kita harus menonaktifkan jejak default. Di bagian 2, saya menunjukkan sesi Extended Events yang saya gunakan untuk menangkap semua peristiwa perubahan ukuran file. Dalam posting ini, saya ingin menunjukkan tampilan yang saya buat untuk membuat konsumsi data acara lebih mudah bagi orang-orang, dan juga untuk menjelaskan beberapa peringatan.
Tampilan yang mudah dicerna
Pertama, saya membuat tampilan yang akan mengekspos bit penting dari data sesi Extended Events, dan meletakkannya di database utilitas yang ada di setiap instance:
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;
Sekarang, ketika seseorang ingin meninjau peristiwa perubahan ukuran file terbaru di server mana pun, mereka menjalankan:
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges ORDER BY StartTimeUTC DESC;
Saat Anda menonaktifkan pelacakan default, file pelacakan tidak akan dihapus, jadi setiap peristiwa dari sebelum perubahan itu masih dapat ditinjau. Saya dapat meminjam dari fakta bahwa jejak default di-hard-code ke jalur yang sama dengan SERVERPROPERTY(N'ErrorLogFileName')
, dan buat tampilan kedua yang menyatukan data di atas dengan lebih banyak data dari pelacakan default:
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;
Tampilan ini menyesuaikan data jejak (ditangkap dalam waktu Timur di semua server kami) ke UTC, dan menangani DST jika sesuai juga. Jika data berada di luar rentang CTE yang disebut dst
, itu akan dinyatakan dalam waktu Timur sebagai gantinya (dan Anda dapat dengan mudah memperbaikinya dengan menambahkan lebih banyak rentang DST). Ada kolom tambahan bernama src
sehingga Anda dapat menanyakan data jejak lama menggunakan:
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges_IncludingTrace WHERE src = 'trace' ORDER BY StartTimeUTC DESC;
Peringatan
Tidak ada yang namanya makan siang gratis! Meskipun saya yakin bahwa penghapusan pelacakan default tidak akan menghasilkan apa-apa atau, kemungkinan besar, berdampak positif pada beban kerja kami, ada beberapa hal yang perlu diingat untuk lingkungan Anda jika Anda memilih untuk mengikuti jalur saya:
- Basis data tidak permanen
Dalam definisi sesi Acara yang Diperpanjang, saya memilih untuk tidak mengimplementasikan
collect_database_name
, dan pada tampilan di atas Anda dapat melihat bahwa saya menyelesaikan ini saat runtime menggunakanDB_NAME(database_id)
. Ada risiko di sini, di mana seseorang dapat membuat database, melakukan banyak aktivitas yang membuat file churn dan disk thrashing, lalu menjatuhkan database.database_id
diekspos dalam XML tidak lagi berarti dalam kasus ini, danDB_NAME()
akan mengembalikanNULL
.Saya memilih hasil ini daripada hanya mengandalkan nama basis data, karena rantai peristiwa di atas jauh lebih kecil kemungkinannya daripada penggantian nama basis data (di mana
database_id
akan tetap sama). Dalam hal ini, Anda mungkin mencari peristiwa yang terjadi pada database, tetapi mencari menggunakan nama (saat ini) yang salah, bergantung pada kapan peristiwa itu terjadi.Jika Anda ingin dapat menggunakan satu atau yang lain, Anda dapat menggunakan definisi sesi berikut sebagai gantinya:
... ADD EVENT sqlserver.database_file_size_change ( SET collect_database_name = (1) ACTION ( sqlserver.sql_text, ...
Ini juga tidak gratis, atau akan terjadi secara default, tetapi saya akui saya belum pernah menguji dampak penambahan itu ke koleksi.
- Laporan SSMS akan sedikit kurang dapat diandalkan
Efek samping dari menonaktifkan pelacakan default adalah mengganggu beberapa "Laporan Standar" Management Studio. Saya telah melakukan polling kepada tim kami sebelum melakukan ini, dan Anda pasti ingin melakukan hal yang sama untuk memastikan pengguna Anda tidak bergantung pada salah satu dari ini. Anda juga ingin mengingatkan mereka bahwa laporan saat ini tidak dapat diandalkan, untuk alasan yang sama saya tidak dapat mengandalkan pelacakan default secara langsung – mereka hanya dapat menarik data yang masih dalam pelacakan. Laporan kosong tidak berarti tidak ada peristiwa yang terjadi; itu bisa saja berarti bahwa informasi tersebut tidak lagi tersedia. Jika ini benar-benar tempat tim ingin menggunakan informasi ini, saya dapat memastikannya dapat diandalkan dengan mengirimkan mereka laporan khusus yang menggunakan sumber yang lebih tepercaya.
Laporan berikut adalah laporan yang saya lihat memperoleh setidaknya sebagian informasinya dari pelacakan default, dan mengapa kami tidak memerlukan laporan tersebut meskipun dapat dipercaya:
Riwayat Perubahan Skema Kami sudah memiliki kontrol sumber, proses peninjauan / penerapan yang ketat, dan pemicu DDL yang menangkap informasi tentang perubahan skema. Riwayat Perubahan Konfigurasi
dan
Konsumsi MemoriAlat pemantauan kami memberi tahu kami tentang perubahan konfigurasi tingkat instans, sehingga laporan di SSMS ini berlebihan. Gagal Masuk Ini ada di log kesalahan (dan penampil acara) karena, sebagai standar, kami mengaktifkan audit "Hanya login gagal" untuk semua contoh SQL Server. Beberapa server juga memiliki audit formal tambahan untuk alasan kepatuhan. Penggunaan Disk Di antara informasi lainnya, ini mencantumkan peristiwa pertumbuhan otomatis dan penyusutan otomatis dari jejak default, yang sekarang kami tangkap menggunakan Peristiwa yang Diperpanjang. Acara Pencadangan dan Pemulihan Informasi ini sudah tersedia di msdb.dbo.backupset jika kami membutuhkannya, tetapi ini juga dimasukkan ke dalam otomatisasi kami seputar pencadangan dan pemulihan (kami tidak pernah melihat jejak default untuk informasi ini).
Riwayat Konsistensi Basis Data Seperti halnya pencadangan, kami memiliki otomatisasi yang dibangun di sekitar DBCC CHECKDB; jika seseorang keluar dari ini dan menjalankan sesuatu secara manual, itu akan tetap muncul di log kesalahan. Dan kami memiliki lebih banyak kendali atas berapa lama kami menyimpan log kesalahan, dan seberapa sering kami mendaur ulangnya. Kami mendaur ulang setiap malam sehingga lebih mudah untuk menemukan peristiwa yang kami duga terjadi pada hari tertentu di masa lalu.
Kesimpulan
Ini adalah proyek yang menyenangkan tetapi rumit, dan saya puas dengan hasilnya sejauh ini. Terima kasih telah menemani!
[ Bagian 1 | Bagian 2 | Bagian 3 ]