Ada sedikit informasi berharga yang secara default dilacak oleh SQL Server. Sejak SQL Server 2005 telah ada "jejak default" yang berjalan di latar belakang, dan sejak SQL Server 2008 telah ada sesi Extended Events yang secara otomatis berjalan, disebut system_health
.
Anda juga dapat menemukan informasi tertentu dari log galat SQL Server, log Agen SQL Server, log peristiwa Windows, dan pencatatan tambahan dari hal-hal seperti Audit SQL Server , Gudang Data Manajemen , Pemberitahuan Kejadian , Pemicu DML , Pemicu DDL , Pemicu DDL , Pemicu SCOM / Pusat Sistem , jejak sisi server Anda sendiri atau sesi Acara yang Diperpanjang, atau solusi pemantauan pihak ketiga (seperti yang dibuat oleh majikan saya, SQL Sentry ). Anda juga dapat secara opsional mengaktifkan apa yang disebut "Jejak Blackbox" untuk membantu dalam pemecahan masalah .
Tetapi untuk posting ini saya akan memfokuskan ruang lingkup pada hal-hal yang umumnya paling diaktifkan di mana-mana: jejak default, sesi Acara yang Diperpanjang, dan log kesalahan.
Jejak Bawaan
Jejak default biasanya berjalan di sebagian besar sistem, kecuali jika Anda menonaktifkannya menggunakansp_configure
. Selama diaktifkan, ini bisa menjadi sumber informasi berharga yang kaya. Berikut ini daftar acara jejak yang ditangkap:
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;
Anda dapat masuk ke detail lebih lanjut dengan bergabung untuk sys.trace_columns
melihat acara mana yang datang dengan data mana, tapi saya akan melewatkannya untuk saat ini, karena Anda dapat melihat apa yang Anda miliki ketika Anda benar-benar meminta data jejak untuk peristiwa tertentu. Ini adalah peristiwa yang tersedia di sistem saya (Anda harus menjalankan kueri pada Anda untuk memastikan mereka cocok, meskipun ini masih set peristiwa yang sama melalui 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
Perhatikan bahwa penelusuran default menggunakan file rollover dan data yang tersedia untuk Anda hanya akan kembali sejauh ini - rentang tanggal data yang tersedia tergantung pada berapa banyak peristiwa di atas yang ditangkap dan pada frekuensi berapa. Jika Anda ingin memastikan bahwa Anda memiliki riwayat yang lebih lama, Anda dapat mengatur pekerjaan yang secara berkala mengarsipkan file yang saat ini tidak aktif yang terkait dengan jejak.
Contohnya
Dalam pertanyaan saya mengajukan beberapa pertanyaan yang saya temukan. Berikut adalah contoh kueri untuk menarik informasi tertentu dari jejak default.
Pertanyaan: Kapan terakhir kali pertumbuhan otomatis terjadi di basis data AdventureWorks, dan berapa lama?
Kueri ini akan menarik semua peristiwa AutoGrow di database AdventureWorks, untuk file log dan data, yang masih dalam file log jejak default:
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;
Pertanyaan: Siapa yang menghapus tabel dbo.EmployeeAuditData dan kapan?
Ini akan mengembalikan DROP
peristiwa apa pun untuk objek bernama EmployeeAuditData
. Jika Anda ingin memastikan bahwa itu hanya mendeteksi DROP
acara untuk tabel, Anda dapat menambahkan filter: ObjectType = 8277
( daftar lengkapnya didokumentasikan di sini ). Jika Anda ingin membatasi ruang pencarian untuk database tertentu, Anda dapat menambahkan filter: 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;
Ada komplikasi di sini, dan ini adalah kasus yang sangat ujung tetapi berpikir itu bijaksana untuk disebutkan pula. Jika Anda menggunakan beberapa skema dan mungkin memiliki nama objek yang sama di beberapa skema, Anda tidak akan dapat mengetahui yang mana ini (kecuali jika masih ada rekannya). Ada kasus luar bahwa UserA mungkin telah menjatuhkan SchemaB.Tablename sementara UserB mungkin telah menjatuhkan SchemaA.Tablename. Jejak default tidak melacak skema objek (juga tidak menangkap TextData
untuk acara ini), danObjectID
termasuk dalam jejak tidak berguna untuk pertandingan langsung (karena objek dijatuhkan dan tidak ada lagi). Termasuk bahwa kolom dalam output dalam hal ini mungkin berguna untuk referensi silang terhadap setiap salinan tabel dengan nama yang sama yang masih ada, tetapi jika sistem dalam banyak kekacauan ini (atau jika semua salinan tersebut telah dihapus) ada masih mungkin bukan cara yang dapat diandalkan untuk menebak di mana salinan tabel dijatuhkan oleh siapa.
Acara yang Diperpanjang
Dari Mendukung SQL Server 2008: Sesi system_health (SQLCSS Blog) , berikut ini adalah daftar data yang dapat Anda ambil dari system_health
sesi di SQL Server 2008 dan 2008 R2:
- Sql_text dan session_id untuk setiap sesi yang menemukan kesalahan dengan tingkat keparahan> = 20
- Sql_text dan session_id untuk sesi apa pun yang mengalami jenis kesalahan "memori" seperti 17803, 701, dll. (Kami menambahkan ini karena tidak semua kesalahan memori adalah tingkat keparahan> = 20)
- Catatan masalah "tidak menghasilkan" (Anda terkadang melihat ini di ERRORLOG sebagai Msg 17883)
- Kebuntuan yang terdeteksi
- Callstack, sql_text, dan session_id untuk setiap sesi yang telah menunggu kait (atau sumber daya menarik lainnya) selama> 15 detik
- Callstack, sql_text, dan session_id untuk sesi apa pun yang telah menunggu kunci> 30 detik
- Callstack, sql_text, dan session_id untuk setiap sesi yang telah menunggu untuk periode waktu yang lama untuk menunggu "eksternal" atau "menunggu lebih dulu".
Dari Gunakan sesi acara system_health (MSDN) , daftar agak diperluas di SQL Server 2012 (dan tetap sama untuk SQL Server 2014):
- The sql_text dan session_id untuk setiap sesi yang menemukan kesalahan yang memiliki tingkat keparahan> = 20.
- Sql_text dan session_id untuk setiap sesi yang mengalami kesalahan terkait memori. Kesalahan termasuk 17803, 701, 802, 8645, 8651, 8657 dan 8902.
- Catatan masalah penjadwal yang tidak menghasilkan apa pun. (Ini muncul di log galat SQL Server sebagai galat 17883.)
- Kebuntuan yang terdeteksi.
- Callstack, sql_text, dan session_id untuk setiap sesi yang telah menunggu kait (atau sumber daya menarik lainnya) selama> 15 detik.
- Callstack, sql_text, dan session_id untuk sesi apa pun yang telah menunggu kunci> 30 detik.
- Callstack, sql_text, dan session_id untuk setiap sesi yang telah menunggu lama untuk menunggu preemptive. Durasi bervariasi berdasarkan jenis tunggu. Pencegahan preemptive adalah di mana SQL Server menunggu panggilan API eksternal.
- Callstack dan session_id untuk alokasi CLR dan kegagalan alokasi virtual.
- Peristiwa ring_buffer untuk broker memori, monitor penjadwal, simpul memori OOM, keamanan, dan konektivitas.
- Komponen sistem dihasilkan dari sp_server_diagnostics.
- Kesehatan instan dikumpulkan oleh scheduler_monitor_system_health_ring_buffer_recorded.
- Kegagalan alokasi CLR.
- Kesalahan konektivitas menggunakan connection_ring_buffer_recorded.
- Kesalahan keamanan menggunakan security_error_ring_buffer_recorded.
Di SQL Server 2016, dua peristiwa lagi ditangkap:
- Ketika suatu proses terbunuh menggunakan
KILL
perintah.
- Ketika SQL Server shutdown telah dimulai.
(Dokumentasi belum diperbarui, tetapi saya membuat blog tentang bagaimana saya menemukan ini dan perubahan lainnya .)
Untuk mendapatkan lebih banyak konfigurasi samar yang berlaku untuk versi spesifik Anda, Anda selalu dapat menjalankan kueri berikut secara langsung, tetapi Anda harus menafsirkan nama dan menguraikan predikat agar cocok dengan daftar bahasa yang lebih alami di atas:
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;
Jika Anda menggunakan Grup yang Tersedia, ada juga dua sesi baru yang Anda temukan berjalan: AlwaysOn_failover
dan AlwaysOn_health
. Anda dapat melihat data yang mereka kumpulkan dengan permintaan berikut:
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;
Sesi acara ini menggunakan target penyangga dering untuk menyimpan data, jadi - seperti kumpulan buffer dan cache rencana - acara yang lebih lama akan dihapus, sehingga Anda tidak akan selalu dapat menarik acara dari rentang tanggal yang Anda inginkan.
Contoh
Dalam pertanyaan saya mengajukan pertanyaan fiktif ini:
Berapa banyak kesalahan terkait memori yang terjadi hari ini?
Berikut ini contoh (dan mungkin tidak terlalu efisien) kueri yang dapat menarik informasi ini dari system_health
sesi:
;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;
(Contoh ini meminjam secara longgar dari posting blog pengantar Amit Banerjee pada system_health
sesi tersebut .)
Untuk informasi lebih lanjut tentang Peristiwa Diperpanjang (termasuk banyak contoh di mana Anda dapat meminta data tertentu), lihat seri blog 31 bagian ini oleh Jonathan Kehayias:
https://www.sqlskills.com/blogs/jonathan/an-xevent-a-day-31-days-of-extended-events/
Catatan eror
SQL Server secara default menyimpan file log kesalahan saat ini ditambah 6 terbaru (tetapi Anda dapat mengubahnya ). Banyak informasi disimpan di sana, termasuk informasi startup (berapa inti yang digunakan, apakah halaman kunci dalam memori diatur, mode otentikasi, dll.) Serta kesalahan dan skenario lain yang cukup parah untuk didokumentasikan (dan tidak ditangkap di tempat lain). Salah satu contoh terbaru adalah seseorang yang mencari ketika database diambil offline. Anda dapat menentukan ini dengan memindai setiap 7 log kesalahan terbaru untuk teks 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';
Saya membahas beberapa detail lain dalam jawaban baru-baru ini , dan ada juga beberapa informasi latar belakang yang baik di toadworld dan juga dalam dokumentasi resmi .
Satu kelompok "kesalahan" yang dicatat oleh log kesalahan secara default - dan dapat membuat informasi penting jatuh lebih cepat - adalah setiap pesan cadangan yang berhasil. Anda dapat mencegah ini mengisi log kesalahan dengan noise dengan mengaktifkan jejak jejak 3226 .