มีข้อมูลที่มีค่าค่อนข้างน้อยที่ SQL Server ติดตามให้คุณตามค่าเริ่มต้น ตั้งแต่ SQL Server 2005 ได้มีการ "ร่องรอยเริ่มต้น" ที่ทำงานในพื้นหลังและตั้งแต่ SQL Server 2008 system_health
ได้มีการขยายกิจกรรมเซสชั่นทำงานโดยอัตโนมัติที่เรียกว่า
นอกจากนี้คุณยังสามารถค้นหาข้อมูลบางอย่างจากบันทึกข้อผิดพลาดของ SQL Server, บันทึกตัวแทนของเซิร์ฟเวอร์ SQL, บันทึกเหตุการณ์ของ Windows, และบันทึกเพิ่มเติมจากสิ่งต่าง ๆ เช่นการตรวจสอบเซิร์ฟเวอร์ SQL , คลังข้อมูลการจัดการ , การแจ้งเตือนเหตุการณ์ , ทริกเกอร์ DML , ทริกเกอร์ DDL , SCOM / System Centerการติดตามฝั่งเซิร์ฟเวอร์ของคุณหรือเซสชันเพิ่มเติมของเหตุการณ์หรือโซลูชันการตรวจสอบบุคคลที่สาม (เช่นที่ทำโดยSQL Sentry ของนายจ้างของฉัน ) นอกจากนี้คุณยังสามารถเลือกที่จะเปิดใช้งานที่เรียกว่า "Blackbox ร่องรอย" เพื่อช่วยในการแก้ไขปัญหา
แต่สำหรับโพสต์นี้ฉันจะเน้นขอบเขตของสิ่งที่เปิดใช้งานได้ทุกที่มากที่สุด: การติดตามเริ่มต้น, เซสชันการขยายกิจกรรมและบันทึกข้อผิดพลาด
การติดตามเริ่มต้น
ร่องรอยเริ่มต้นมักจะทำงานบนระบบส่วนใหญ่จนกว่าคุณจะได้ปิดการใช้งานได้โดยใช้ 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.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 Blog)ต่อไปนี้เป็นรายการข้อมูลที่คุณสามารถคัดออกจากsystem_health
เซสชันใน SQL Server 2008 และ 2008 R2:
- sql_text และ session_id สำหรับเซสชันใด ๆ ที่พบข้อผิดพลาดที่มีความรุนแรง> = 20
- sql_text และ session_id สำหรับเซสชันใด ๆ ที่พบข้อผิดพลาดประเภท "หน่วยความจำ" เช่น 17803, 701 ฯลฯ (เราเพิ่มสิ่งนี้เพราะไม่ใช่ข้อผิดพลาดของหน่วยความจำทั้งหมดจะรุนแรง> = 20)
- บันทึกปัญหา "ที่ไม่ยอมทำ" (บางครั้งคุณเคยเห็นสิ่งเหล่านี้ใน ERRORLOG เป็นข่าวสารเกี่ยวกับ 17883)
- การหยุดชะงักใด ๆ ที่ตรวจพบ
- callstack, sql_text และ session_id สำหรับเซสชันใด ๆ ที่รอการรอ (หรือทรัพยากรที่น่าสนใจอื่น ๆ ) เป็นเวลา> 15 วินาที
- callstack, sql_text และ session_id สำหรับเซสชันใด ๆ ที่รอการล็อคเป็นเวลา> 30 วินาที
- callstack, 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)
- การหยุดชะงักใด ๆ ที่ตรวจพบ
- callstack, sql_text และ session_id สำหรับเซสชันใด ๆ ที่รออยู่กับแลตช์ (หรือทรัพยากรที่น่าสนใจอื่น ๆ ) เป็นเวลา> 15 วินาที
- callstack, sql_text และ session_id สำหรับเซสชันใด ๆ ที่รอการล็อคเป็นเวลา> 30 วินาที
- callstack, sql_text และ session_id สำหรับเซสชันใด ๆ ที่รอมาเป็นเวลานานสำหรับการจองล่วงหน้า ระยะเวลาแตกต่างกันไปตามประเภทการรอ การรอคอยแบบ preemptive คือที่ซึ่งเซิร์ฟเวอร์ SQL กำลังรอการเรียก API ภายนอก
- callstack และ session_id สำหรับการจัดสรร CLR และการจัดสรรเสมือนล้มเหลว
- เหตุการณ์ ring_buffer สำหรับนายหน้าหน่วยความจำมอนิเตอร์ตัวกำหนดตารางเวลาโหนดโหนด OOM ความปลอดภัยและการเชื่อมต่อ
- ส่วนประกอบของระบบเป็นผลมาจาก sp_server_diagnostics
- สถานะอินสแตนซ์ที่รวบรวมโดย scheduler_monitor_system_health_ring_buffer_recorded
- การจัดสรร CLR ล้มเหลว
- ข้อผิดพลาดการเชื่อมต่อโดยใช้ connection_ring_buffer_recorded
- ข้อผิดพลาดด้านความปลอดภัยโดยใช้ security_error_ring_buffer_recorded
ใน SQL Server 2016 จะมีการจับภาพอีกสองเหตุการณ์:
- เมื่อกระบวนการถูกฆ่าโดยใช้
KILL
คำสั่ง
- เมื่อการปิด SQL Server เริ่มขึ้น
(เอกสารยังไม่ได้รับการปรับปรุงแต่ฉัน blogged เกี่ยวกับวิธีที่ฉันค้นพบการเปลี่ยนแปลงเหล่านี้และอื่น ๆ )
หากต้องการรับการกำหนดค่าที่มีความลับเพิ่มเติมที่ใช้กับเวอร์ชันเฉพาะของคุณคุณสามารถเรียกใช้คิวรีต่อไปนี้ได้โดยตรง แต่คุณจะต้องแปลชื่อและแยกเพรดิเคตให้ตรงกับรายการภาษาที่เป็นธรรมชาติด้านบน:
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
เซสชั่น )
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Extended Events (รวมถึงตัวอย่างมากมายที่คุณสามารถค้นหาข้อมูลที่เฉพาะเจาะจง) ดูชุดบล็อก 31 ส่วนโดย Jonathan Kehayias:
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';
ฉันครอบคลุมรายละเอียดอื่น ๆ บางส่วนในคำตอบที่ผ่านมานี้และนอกจากนี้ยังมีข้อมูลพื้นฐานบางอย่างที่ดีที่ toadworldและในเอกสารอย่างเป็นทางการ
กลุ่มหนึ่งของ "ข้อผิดพลาด" บันทึกข้อผิดพลาดจะติดตามโดยค่าเริ่มต้น - และสามารถทำให้ข้อมูลที่สำคัญหลุดออกจากหางได้เร็วกว่ามาก - คือทุกข้อความสำรองที่ประสบความสำเร็จ คุณสามารถป้องกันเหล่านี้จากการเติมขึ้นบันทึกข้อผิดพลาดที่มีสัญญาณรบกวนโดยการเปิดใช้งานการติดตามธง 3226