Існує досить багато цінної інформації, яку SQL Server відстежує для вас за замовчуванням. З часу SQL Server 2005 з'явився "слід за замовчуванням", який працює у фоновому режимі, а з часу SQL Server 2008 сеанс розширених подій автоматично запускається, називається system_health
.
Ви також можете знайти певну інформацію з журналу SQL Server помилок, журнал агента SQL Server, журнали подій Windows, а також додаткові протоколювання від таких речей , як аудит SQL Server , управління сховища даних , повідомлення про події , DML Тригери , DDL тригери , SCOM / System Center , ваші власні сліди або сеанси розширених подій або сторонні моніторингові рішення (наприклад, зроблені моїм роботодавцем, SQL Sentry ). Ви також можете ввімкнути так званий "слід чорного поля", щоб допомогти у вирішенні проблем .
Але для цієї публікації я хочу зосередити увагу на речах, які загалом увімкнено найбільше: слід за замовчуванням, сеанси розширених подій та журнал помилок.
Трасування за замовчуванням
Трасування за замовчуванням зазвичай працює в більшості систем, якщо ви його не відключили за допомогоюsp_configure
. Поки це ввімкнено, це може бути багатим джерелом цінної інформації. Далі перелічено дані про відстежувані події:
DECLARE @TraceID INT;
SELECT @TraceID = id FROM sys.traces WHERE is_default = 1;
SELECT t.EventID, e.name as Event_Description
FROM sys.fn_trace_geteventinfo(@TraceID) t
JOIN sys.trace_events e ON t.eventID = e.trace_event_id
GROUP BY t.EventID, e.name;
Ви можете отримати більш детальну інформацію, приєднавшись, щоб sys.trace_columns
побачити, які події надходять із якими даними, але я зараз пропускаю це, оскільки ви можете бачити, що у вас є, коли ви фактично запитуєте дані про сліди для конкретних подій. Це події, які доступні в моїй системі (слід запустити запит на свою, щоб переконатися, що вони відповідають, хоча це все той же набір подій через SQL Server 2019 CTP 2.4):
EventID Event_Description
------- ----------------------------------------------
18 Audit Server Starts And Stops
20 Audit Login Failed
22 ErrorLog
46 Object:Created
47 Object:Deleted
55 Hash Warning
69 Sort Warnings
79 Missing Column Statistics
80 Missing Join Predicate
81 Server Memory Change
92 Data File Auto Grow
93 Log File Auto Grow
94 Data File Auto Shrink
95 Log File Auto Shrink
102 Audit Database Scope GDR Event
103 Audit Schema Object GDR Event
104 Audit Addlogin Event
105 Audit Login GDR Event
106 Audit Login Change Property Event
108 Audit Add Login to Server Role Event
109 Audit Add DB User Event
110 Audit Add Member to DB Role Event
111 Audit Add Role Event
115 Audit Backup/Restore Event
116 Audit DBCC Event
117 Audit Change Audit Event
152 Audit Change Database Owner
153 Audit Schema Object Take Ownership Event
155 FT:Crawl Started
156 FT:Crawl Stopped
164 Object:Altered
167 Database Mirroring State Change
175 Audit Server Alter Trace Event
218 Plan Guide Unsuccessful
Зауважте, що трасування за замовчуванням використовує файли перекидання, і тому доступні вам дані будуть повертатися лише поки далеко - діапазон дат доступних даних залежить від того, скільки вищезазначених подій фіксуються та з якою частотою. Якщо ви хочете забезпечити збереження більш тривалої історії, ви можете налаштувати завдання, яке періодично архівує поточні неактивні файли, пов’язані з трасуванням.
Приклади
У запитанні я задав пару питань, які знайшов. Ось приклади запитів для витягання конкретної інформації з трасування за замовчуванням.
Питання: Коли востаннє в базі даних AdventureWorks траплялося автоматичне зростання, і скільки часу це зайняло?
Цей запит витягне всі події AutoGrow у базі даних AdventureWorks, як для журналів, так і для файлів даних, які все ще знаходяться у файлах журналу слідів за замовчуванням:
DECLARE @path NVARCHAR(260);
SELECT
@path = REVERSE(SUBSTRING(REVERSE([path]),
CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM sys.traces
WHERE is_default = 1;
SELECT
DatabaseName,
[FileName],
SPID,
Duration,
StartTime,
EndTime,
FileType = CASE EventClass WHEN 92 THEN 'Data' ELSE 'Log' END
FROM sys.fn_trace_gettable(@path, DEFAULT)
WHERE EventClass IN (92,93)
AND DatabaseName = N'AdventureWorks'
ORDER BY StartTime DESC;
Питання: Хто видалив таблицю dbo.E EmployeeAuditData і коли?
Це поверне будь-які DROP
події для об'єкта з іменем EmployeeAuditData
. Якщо ви хочете переконатися, що він виявляє лише DROP
події для таблиць, ви можете додати фільтр: ObjectType = 8277
( повний список тут задокументований ). Якщо ви хочете , щоб обмежити область пошуку для конкретної бази даних, ви можете додати фільтр: DatabaseName = N'db_name'
.
DECLARE @path NVARCHAR(260);
SELECT
@path = REVERSE(SUBSTRING(REVERSE([path]),
CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM sys.traces
WHERE is_default = 1;
SELECT
LoginName,
HostName,
StartTime,
ObjectName,
TextData
FROM sys.fn_trace_gettable(@path, DEFAULT)
WHERE EventClass = 47 -- Object:Deleted
AND EventSubClass = 1
AND ObjectName = N'EmployeeAuditData'
ORDER BY StartTime DESC;
Тут є складність, і це дуже крайній випадок, але він вважав за доцільне згадати все одно. Якщо ви використовуєте декілька схем і можуть мати одне і те ж ім'я об'єкта в декількох схемах, ви не зможете сказати, що це (якщо тільки його колеги все ще не існують). Існує зовнішній випадок, що UserA, можливо, скинув SchemaB.Tablename, тоді як UserB, можливо, скинув SchemaA.Tablename. Шлях за замовчуванням не відстежує схему об'єкта (а також не фіксує TextData
для цієї події), аObjectID
включений у трас не корисний для прямої відповідності (тому що об’єкт був скинутий і більше не існує). Включення цього стовпця у висновок у цьому випадку може бути корисним для перехресного посилання на будь-які копії таблиці з тим самим іменем, які все ще існують, але якщо система перебуває в такому великому розладі (або якщо всі такі копії були видалені) там як і раніше не може бути надійним способом здогадатися, на кого кинула копія таблиці.
Розширені події
З підтримки SQL Server 2008: сесія system_health (блог SQLCSS) , подано список даних, які можна вилучити з system_health
сеансу в SQL Server 2008 та 2008 R2:
- Sql_text і session_id для будь-яких сеансів, які зустрічаються з помилкою помилки> = 20
- Sql_text і session_id для будь-яких сеансів, які стикаються з помилками типу "пам'яті", такими як 17803, 701, і т. Д. (Ми додали це, оскільки не всі помилки пам'яті є серйозністю> = 20)
- Запис про будь-які "непоступливі" проблеми (ви їх іноді бачили в ERRORLOG як Msg 17883)
- Будь-які виявлені тупики
- Столик викликів, sql_text і session_id для будь-яких сеансів, які чекали на засувки (або інші цікаві ресурси) протягом> 15 секунд
- Столик дзвінків, sql_text і session_id для будь-яких сеансів, які чекали на блокування протягом> 30 секунд
- Стойка дзвінків, sql_text і session_id для будь-якого сеансу, який чекав тривалий час на "зовнішнє" очікування або "випереджальне очікування".
З використання сесії подій system_health (MSDN) список дещо розширений у SQL Server 2012 (і залишається тим самим для SQL Server 2014):
- Sql_text і session_id для будь-яких сеансів, які стикаються з помилкою, що має серйозність> = 20.
- Sql_text і session_id для будь-яких сеансів, які стикаються з помилкою, пов'язаною з пам'яттю. До помилок відносяться 17803, 701, 802, 8645, 8651, 8657 та 8902.
- Запис про будь-які непоступні проблеми з планувальником. (Вони відображаються в журналі помилок SQL Server як помилка 17883.)
- Будь-які виявлені тупики.
- Стойка дзвінків, sql_text і session_id для будь-яких сеансів, які чекали на засувках (або інших цікавих ресурсах) більше 15 секунд.
- Стойка дзвінків, sql_text і session_id для будь-яких сеансів, які чекали на блокування більше 30 секунд.
- Стойка дзвінків, sql_text і session_id для будь-яких сеансів, які довго чекали на випереджальне очікування. Тривалість залежить від типу очікування. Передумови очікування - це те, коли SQL Server чекає зовнішніх дзвінків API.
- Столик викликів і session_id для розподілу CLR і відмов віртуального розподілу.
- Події ring_buffer для брокера пам'яті, монітора планувальника, OOM вузла пам'яті, безпеки та підключення.
- Системний компонент є результатом sp_server_diagnostics.
- Екземпляр здоров’я, зібраний програмою-планувальником_monitor_system_health_ring_buffer_recorded.
- Збої в розподілі CLR.
- Помилки підключення з використанням записаних на зв’язок_ring_buffer_.
- Помилки безпеки при використанні security_error_ring_buffer_recorded.
У SQL Server 2016 фіксуються ще дві події:
- Коли процес вбивається за допомогою
KILL
команди.
- Коли було запущено відключення SQL Server.
(Документація ще не оновлена, але я блогів про те, як я виявляю ці та інші зміни .)
Щоб отримати більш чітко налаштовану конфігурацію, застосовну для вашої конкретної версії, ви завжди можете запустити наступний запит безпосередньо, але вам доведеться інтерпретувати імена та аналізувати предикати, щоб відповідати більш природним спискам мов, наведеним вище:
SELECT e.package, e.event_id, e.name, e.predicate
FROM sys.server_event_session_events AS e
INNER JOIN sys.server_event_sessions AS s
ON e.event_session_id = s.event_session_id
WHERE s.name = N'system_health'
ORDER BY e.package, e.name;
Якщо ви використовуєте Групи доступності, ви також знайдете два нові сеанси: AlwaysOn_failover
і AlwaysOn_health
. Ви можете бачити дані, які вони збирають, за допомогою наступного запиту:
SELECT s.name, e.package, e.event_id, e.name, e.predicate
FROM sys.server_event_session_events AS e
INNER JOIN sys.server_event_sessions AS s
ON e.event_session_id = s.event_session_id
WHERE s.name LIKE N'AlwaysOn[_]%'
ORDER BY s.name, e.package, e.name;
Ці сеанси подій використовують цілі буфера кільця для зберігання даних, тому - як буфер буфера та кеш плану - старіші події будуть припинені, тому вам не обов’язково вдасться витягнути події з потрібного діапазону дат.
Приклад
У запитанні я поставив це вигадане питання:
Скільки помилок, пов’язаних із пам’яттю, сталося сьогодні?
Ось зразок (і, мабуть, не дуже ефективний) запит, який може витягнути цю інформацію з system_health
сеансу:
;WITH src(x) AS
(
SELECT y.query('.')
FROM
(
SELECT x = CONVERT(XML, t.target_data)
FROM sys.dm_xe_sessions AS s
INNER JOIN sys.dm_xe_session_targets AS t
ON s.[address] = t.event_session_address
WHERE s.name = N'system_health'
) AS x
CROSS APPLY x.x.nodes('/RingBufferTarget/event') AS y(y)
)
SELECT
x, ts = CONVERT(DATETIME, NULL), err = CONVERT(INT, NULL)
INTO #blat FROM src;
DELETE #blat WHERE x.value('(/event/@name)[1]', 'varchar(255)') <> 'error_reported';
UPDATE #blat SET ts = x.value('(/event/@timestamp)[1]', 'datetime');
UPDATE #blat SET err = x.value('(/event/data/value)[1]', 'int');
SELECT err, number_of_events = COUNT(*)
FROM #blat
WHERE err IN (17803, 701, 802, 8645, 8651, 8657, 8902)
AND ts >= CONVERT(DATE, CURRENT_TIMESTAMP)
GROUP BY err;
DROP TABLE #blat;
(Цей приклад вільно запозичується з вступної публікації блогу Amit Banerjee на system_health
сесії .)
Для отримання додаткової інформації про розширені події (включаючи безліч прикладів, де можна отримати запит на конкретні дані), перегляньте цю серію блогів, що складається з 31 частини Джонатана Кехаяса:
https://www.sqlskills.com/blogs/jonathan/an-xevent-a-day-31-days-of-extended-events/
Журнал помилок
За замовчуванням SQL Server зберігає поточні плюс 6 останніх файлів журналу помилок (але ви можете змінити це ). Там зберігається багато інформації, включаючи інформацію про запуск (скільки ядер використовується, чи встановлено блокування сторінок у пам'яті, режим аутентифікації тощо), а також помилки та інші сценарії, досить серйозні, щоб бути задокументованими (а не захоплено в іншому місці). Одним із останніх прикладів був той, хто шукав, коли база даних була знята в автономному режимі. Визначити це можна, просканувавши кожен із останніх 7 журналів помилок для тексту Setting database option OFFLINE
:
EXEC sys.sp_readerrorlog 0,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 1,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 2,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 3,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 4,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 5,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 6,1,'Setting database option OFFLINE';
У цій нещодавній відповіді я висвітлював деякі інші деталі , а також є хороша довідкова інформація у світі події та також в офіційній документації .
Одна група "помилок" журналу помилок відстежує за замовчуванням - і може зробити важливу інформацію набагато швидше падати з хвоста - це кожне успішне повідомлення про резервну копію. Ви можете запобігти заповненню журналу помилок шумом, включивши прапор 3226 сліду .