[Phần 1 | Phần 2 | Phần 3]
Trong phần 1 của loạt bài này, tôi đã giải thích cách tôi đi đến kết luận rằng chúng ta nên vô hiệu hóa dấu vết mặc định. Trong phần 2, tôi đã hiển thị phiên Sự kiện mở rộng mà tôi đã triển khai để nắm bắt tất cả các sự kiện thay đổi kích thước tệp. Trong bài đăng này, tôi muốn hiển thị các chế độ xem mà tôi đã tạo để giúp mọi người sử dụng dữ liệu sự kiện dễ dàng hơn và cũng để giải thích một số lưu ý.
Chế độ xem có thể hiểu được
Đầu tiên, tôi đã tạo một dạng xem sẽ hiển thị các bit quan trọng từ dữ liệu phiên Sự kiện mở rộng và đặt nó vào cơ sở dữ liệu tiện ích tồn tại trên mọi phiên bản:
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;
Bây giờ, khi ai đó muốn xem lại các sự kiện thay đổi kích thước tệp gần đây trên bất kỳ máy chủ nào, họ chạy:
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges ORDER BY StartTimeUTC DESC;
Khi bạn vô hiệu hóa theo dõi mặc định, các tệp theo dõi sẽ không bị xóa, vì vậy mọi sự kiện từ trước thay đổi đó vẫn có thể xem lại được. Tôi có thể mượn từ thực tế là dấu vết mặc định được mã hóa cứng đến cùng một đường dẫn với SERVERPROPERTY(N'ErrorLogFileName')
và tạo chế độ xem thứ hai kết hợp dữ liệu trên với nhiều dữ liệu hơn từ dấu vết mặc định:
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;
Chế độ xem này điều chỉnh dữ liệu theo dõi (được ghi lại theo giờ miền Đông trên tất cả các máy chủ của chúng tôi) thành UTC và cũng xử lý DST nếu thích hợp. Nếu dữ liệu nằm ngoài phạm vi của CTE được gọi là dst
, thay vào đó, nó sẽ được biểu thị theo giờ miền Đông (và bạn có thể dễ dàng sửa lỗi này bằng cách thêm nhiều dải DST hơn). Có một cột bổ sung được gọi là src
vì vậy bạn có thể truy vấn dữ liệu theo dõi cũ bằng cách sử dụng:
SELECT <cols> FROM UtilityDatabase.dbo.vwFileSizeChanges_IncludingTrace WHERE src = 'trace' ORDER BY StartTimeUTC DESC;
Lưu ý
Không có cái gọi là bữa trưa miễn phí! Mặc dù tôi tin tưởng rằng việc xóa dấu vết mặc định sẽ không có hoặc nhiều khả năng là tác động tích cực đến khối lượng công việc của chúng tôi, nhưng có một số điều cần lưu ý đối với môi trường của bạn nếu bạn chọn đi theo con đường của tôi:
- Cơ sở dữ liệu không vĩnh viễn
Trong định nghĩa phiên Sự kiện mở rộng của mình, tôi đã chọn không triển khai
collect_database_name
và trong giao diện ở trên, bạn có thể thấy rằng tôi giải quyết vấn đề này trong thời gian chạy bằng cách sử dụngDB_NAME(database_id)
. Có một rủi ro ở đây, đó là ai đó có thể tạo cơ sở dữ liệu, thực hiện một loạt các hoạt động tạo ra sự xáo trộn tệp và đập đĩa, sau đó làm rơi cơ sở dữ liệu.database_id
được hiển thị trong XML không còn có ý nghĩa trong trường hợp này vàDB_NAME()
sẽ trả vềNULL
.Tôi đã chọn kết quả này thay vì chỉ dựa vào tên cơ sở dữ liệu, bởi vì chuỗi sự kiện trên ít có khả năng xảy ra hơn so với việc đổi tên cơ sở dữ liệu (trong đó
database_id
sẽ giữ nguyên). Trong trường hợp đó, bạn có thể đang tìm kiếm các sự kiện đã xảy ra với cơ sở dữ liệu, nhưng tìm kiếm bằng cách sử dụng sai tên (hiện tại), tùy thuộc vào thời điểm các sự kiện xảy ra.Nếu bạn muốn có thể sử dụng cái này hoặc cái kia, bạn có thể sử dụng định nghĩa phiên sau để thay thế:
... ADD EVENT sqlserver.database_file_size_change ( SET collect_database_name = (1) ACTION ( sqlserver.sql_text, ...
Điều này cũng không thể miễn phí hoặc nó sẽ xảy ra theo mặc định, nhưng tôi thú thực là tôi chưa bao giờ kiểm tra tác động của việc thêm nó vào bộ sưu tập.
- Báo cáo SSMS sẽ kém tin cậy hơn một chút
Một tác dụng phụ của việc tắt theo dõi mặc định là làm gián đoạn một số "Báo cáo chuẩn" của Management Studio. Tôi đã thăm dò ý kiến các nhóm của chúng tôi trước khi thực hiện việc này và bạn sẽ muốn làm điều tương tự để đảm bảo người dùng của bạn không dựa vào bất kỳ điều nào trong số này. Bạn cũng sẽ muốn nhắc họ rằng dù sao thì các báo cáo hiện không thể dựa vào được, vì lý do tương tự mà tôi không thể dựa trực tiếp vào dấu vết mặc định - họ chỉ có thể lấy dữ liệu vẫn còn trong dấu vết. Một báo cáo trống không nhất thiết có nghĩa là không có sự kiện nào xảy ra; nó có thể có nghĩa là thông tin không còn nữa. Nếu đây thực sự là nơi một nhóm muốn sử dụng thông tin này, tôi có thể đảm bảo rằng thông tin đó đáng tin cậy bằng cách gửi cho họ các báo cáo tùy chỉnh sử dụng nguồn đáng tin cậy hơn.
Các báo cáo sau đây là những báo cáo mà tôi có thể thấy lấy được ít nhất một số thông tin của chúng từ dấu vết mặc định và tại sao chúng tôi không cần báo cáo ngay cả khi chúng có thể đáng tin cậy:
Lịch sử thay đổi giản đồ Chúng tôi đã có quyền kiểm soát nguồn, quy trình xem xét / triển khai nghiêm ngặt và các trình kích hoạt DDL tại chỗ để nắm bắt thông tin về các thay đổi giản đồ. Lịch sử thay đổi cấu hình
và
Tiêu thụ bộ nhớCông cụ giám sát của chúng tôi cho chúng tôi biết về các thay đổi cấu hình cấp phiên bản, vì vậy, báo cáo này trong SSMS là không cần thiết. Đăng nhập không thành công Những điều này nằm trong nhật ký lỗi (và trình xem sự kiện) vì theo tiêu chuẩn, chúng tôi bật kiểm tra "Chỉ đăng nhập không thành công" cho tất cả các phiên bản SQL Server. Một số máy chủ cũng có kiểm tra chính thức bổ sung vì lý do tuân thủ. Sử dụng đĩa Trong số các thông tin khác, phần này liệt kê các sự kiện tự động phát triển và tự động rút ra từ dấu vết mặc định, hiện chúng tôi nắm bắt bằng cách sử dụng Sự kiện mở rộng. Sao lưu và khôi phục sự kiện Thông tin này có sẵn trong msdb.dbo.backupset nếu chúng tôi cần, nhưng điều này cũng được đưa vào quá trình tự động hóa của chúng tôi xung quanh việc sao lưu và khôi phục (chúng tôi không bao giờ xem xét dấu vết mặc định cho thông tin này).
Lịch sử nhất quán của cơ sở dữ liệu Cũng như các bản sao lưu, chúng tôi đã xây dựng tự động hóa xung quanh DBCC CHECKDB; nếu ai đó đã ra ngoài và chạy một cái gì đó theo cách thủ công, nó sẽ vẫn hiển thị trong nhật ký lỗi. Và chúng tôi có nhiều quyền kiểm soát hơn đối với thời gian chúng tôi lưu giữ nhật ký lỗi và tần suất chúng tôi tái chế chúng. Chúng tôi tái chế hàng đêm để dễ dàng tìm thấy sự kiện mà chúng tôi nghi ngờ đã xảy ra vào một ngày nhất định trong quá khứ.
Kết luận
Đây là một dự án vui vẻ nhưng phức tạp, và tôi hài lòng với kết quả cho đến nay. Cảm ơn bạn đã đồng hành!
[Phần 1 | Phần 2 | Phần 3]