SQL Server'dan varsayılan olarak hangi olay bilgilerini alabilirim?


60

İnsanların belirli bir şeyin olup olmadığını veya ne zaman gerçekleştiğini veya eylemi kimin gerçekleştirdiğini bilmek istedikleri soruları sıklıkla görüyorum. Pek çok durumda, SQL Server bu bilgiyi kendi başına izlemez. Örneğin:

  • En son kim saklı prosedürü uyguladı dbo.MyProcedure?
  • Tablodaki salarysütunu kim güncelledi dbo.Employees?
  • dbo.OrdersMasayı en son Management Studio'dan kim sorguladı ?

Ama Sunucu SQL diğer bazı olaylar vardır vermez varsayılan olarak geçici izlemek ve doğal gibi ilgili soruları, cevap verebilir:

  • En son ne zaman AdventureWorks veritabanında bir otomatik büyüme oldu ve bu ne kadar sürdü?
  • dbo.EmployeeAuditDataMasayı kim ve ne zaman sildi ?
  • Bugün bellekle ilgili kaç hata oldu?

Bu bilgiyi nasıl alabilirim ve ne kadar süre kullanılabilir kalıyor?

Yanıtlar:


65

SQL Server'ın varsayılan olarak sizin için izlediği oldukça değerli bilgiler var. SQL Server 2005'ten beri arka planda çalışan bir "varsayılan izleme" olmuştur ve SQL Server 2008'den beri otomatik olarak çalışan bir Genişletilmiş Olaylar oturumu vardır system_health.

Ayrıca belirli bilgileri SQL Server hata günlüğünden, SQL Server Agent günlüğünden, Windows olay günlüğünden ve SQL Server Denetimi , Yönetim Veri Ambarı , Olay Bildirimleri , DML Tetikleyicileri , DDL Tetikleyicileri , SCOM / Sistem Merkezi gibi şeylerden gelen ek günlük bilgileri de bulabilirsiniz. kendi sunucu tarafınızdaki izler veya Genişletilmiş Etkinlikler oturumları veya üçüncü taraf izleme çözümleri ( işverenim SQL Sentry tarafından yapılanlar gibi ). İsteğe bağlı olarak , sorun gidermeye yardımcı olması için "Blackbox izleme" adı verilen bir özelliği de etkinleştirebilirsiniz .

Ancak bu yazı için kapsamı her yerde genellikle en etkin olan şeylere odaklayacağım: varsayılan izleme, Genişletilmiş Olaylar oturumları ve hata günlüğü.

Varsayılan İzleme

Varsayılan izleme, kullanmayı devre dışı bırakmadığınızsp_configure sürece genellikle çoğu sistemde çalışır . Etkin olduğu sürece, bu, zengin bir değerli bilgi kaynağı olabilir. Aşağıdakiler yakalanan izleme olaylarını listeler:

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_columnsHangi olayların hangi verilerle geldiğini görmek için katılarak daha fazla ayrıntıya girebilirsiniz , ancak şimdilik bunu atlayacağım, çünkü belirli olaylar için izleme verilerini gerçekten sorguladığınızda ne olduğunu görebilirsiniz. Bunlar sistemimde mevcut olan olaylar (eşleşmelerini sağlamak için sorguyu sizde çalıştırmalısınız, yine de bu, SQL Server 2019 CTP 2.4 ile aynı olay kümesi olmasına rağmen):

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

Varsayılan izlemenin rollover dosyaları kullandığını ve bu nedenle size sunulan verilerin yalnızca şu ana kadar geri döneceğini unutmayın; mevcut verilerin tarih aralığı, yukarıdaki olayların kaç tanesinin yakalandığına ve hangi sıklıkta yapıldığına bağlıdır. Daha uzun bir geçmişi sakladığınızdan emin olmak istiyorsanız, izlemeyle ilişkili olarak etkin olmayan dosyaları periyodik olarak arşivleyen bir iş ayarlayabilirsiniz.

Örnekler

Soruda bulduğum birkaç soru sordum. İşte bu belirli bilgileri varsayılan izlemeden almak için örnek sorgular.

Soru: En son ne zaman AdventureWorks veritabanında bir otomatik büyüme oldu ve bu ne kadar sürdü?

Bu sorgu, hala varsayılan izleme günlük dosyalarında bulunan günlük ve veri dosyaları için AdventureWorks veritabanındaki tüm AutoGrow olaylarını çeker:

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;

Soru: dbo.EmployeeAuditData tablosunu kim ve ne zaman sildi?

Bu DROPadında bir nesne için herhangi bir olay döndürür EmployeeAuditData. Yalnızca DROPtablolar için olayları algıladığından emin olmak istiyorsanız, bir filtre ekleyebilirsiniz: ObjectType = 8277( tam liste burada belgelenmiştir ). Belirli bir veritabanına arama alanını kısıtlamak istiyorsanız, bir filtre ekleyebilirsiniz: 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;

Burada bir komplikasyon var ve bu çok uç bir durum ama yine de bahsetmeye istekliydi. Birden fazla şema kullanıyorsanız ve birden fazla şemada aynı nesne adına sahipseniz, bunun hangisi olduğunu söyleyemezsiniz (karşı taraf (lar) hala mevcut değilse). KullanıcıA'nın SchemaB.Tablename'i bırakmış olabileceği bir dış durum vardır. Varsayılan izleme , nesnenin şemasını izlemez ( TextDatabu olay için de yakalamaz ) veObjectIDize dahil edilen doğrudan bir eşleşme için kullanışlı değildir (çünkü nesne bırakılmış ve artık mevcut değildir). Bu durumda çıktıya bu sütunu dahil etmek, tablonun herhangi bir kopyasına hala aynı isimle sahip olmakla, ancak sistem bu kadar kargaşa içindeyse (veya tüm bu kopyaların silinmiş olması durumunda) çapraz referans vermek için faydalı olabilir. Yine de, tablonun hangi kopyasının kimin tarafından bırakıldığını tahmin etmenin güvenilir bir yolu olmayabilir.

Genişletilmiş Etkinlikler

Gönderen SQL Server 2008 Destekleyen: system_health oturumu (SQLCSS Blog) aşağıdaki aralarından itlaf veri listesi aşağıdadır system_healthSQL Server 2008 ve 2008 R2 oturumu:

  • Ciddiyetle hatayla karşılaşan oturumlar için sql_text ve session_id> = 20
  • Sql_text ve session_id, 17803, 701 vb. Gibi bir "bellek" hatasıyla karşılaşan oturumlar için (tüm bellek hatalarının ciddiyeti olmadığı için bunu ekledik> = 20)
  • Herhangi bir "verimsiz" sorunun kaydı (bunları ERRORLOG'da Msg 17883 olarak gördünüz)
  • Tespit edilen kilitlenmeler
  • Mandallarda (veya diğer ilginç kaynaklarda)> 15 saniye beklemiş olan oturumlar için callstack, sql_text ve session_id
  • Çağrılar, sql_text ve session_id,> 30 saniye boyunca kilitlerde bekleyen oturumlar için
  • "Harici" bekler veya "önleyici bekler" için uzun süre beklemiş olan herhangi bir oturum için çağrı işareti, sql_text ve session_id.

Gönderen Kullanım system_health olay oturumu (MSDN) , liste biraz SQL Server 2012 genişletilmiş (ve SQL Server 2014 için aynı kalır) olduğu:

  • Sql_text ve session_id, önem derecesi> 20 olan bir hatayla karşılaşan oturumlar için.
  • Bellekle ilgili bir hatayla karşılaşan tüm oturumlar için sql_text ve session_id. Hatalar 17803, 701, 802, 8645, 8651, 8657 ve 8902'yi içerir.
  • Getirici olmayan zamanlayıcı sorunlarının bir kaydı. (Bunlar, SQL Server hata günlüğünde 17883 hatası olarak görünür.)
  • Tespit edilen kilitlenmeler.
  • Çağrılar, sql_text ve session_id, mandallarda (veya diğer ilginç kaynaklar)> 15 saniye beklemiş olan oturumlar için.
  • Çağrılar, sql_text ve session_id,> 30 saniye boyunca kilitlerde bekleyen oturumlar için.
  • Çağrıcı, sql_text ve session_id, uzun süre beklemiş olan beklemeler için herhangi bir oturum için. Süre, bekleme türüne göre değişir. Öncelikli bir bekleme, SQL Server'ın harici API çağrıları için beklediği yerdir.
  • CLR tahsisi ve sanal tahsis başarısızlıkları için çağrı dizisi ve session_id.
  • Bellek aracısı, zamanlayıcı izleyicisi, OOM bellek düğümü, güvenlik ve bağlantı için ring_buffer olayları.
  • Sistem bileşeni sp_server_diagnostics'ten kaynaklanıyor.
  • Scheduler_monitor_system_health_ring_buffer_recorded tarafından toplanan örnek sağlığı.
  • CLR Tahsis başarısızlıkları.
  • Connectivity_ring_buffer_recorded kullanarak bağlantı hataları.
  • Security_error_ring_buffer_recorded kullanarak güvenlik hataları.

SQL Server 2016'da iki olay daha yakalanır:

  • Bir işlem KILLkomut kullanılarak öldürüldüğünde .
  • SQL Server kapanması başlatıldığında.

(Dokümantasyon henüz güncellenmedi, ancak bunları ve diğer değişiklikleri nasıl keşfettiğim hakkında blog yazdım .)

Özel sürümünüz için daha şifreli bir konfigürasyon elde etmek için, aşağıdaki sorguyu her zaman doğrudan çalıştırabilirsiniz, ancak isimleri yorumlamanız ve tahminleri yukarıdaki daha doğal dil listelerine uyacak şekilde ayrıştırmanız gerekir:

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;

Kullanılabilirlik Grupları kullanıyorsanız, koşarken bulacağınız iki yeni oturum vardır: AlwaysOn_failoverve AlwaysOn_health. Topladıkları verileri aşağıdaki sorgu ile görebilirsiniz:

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;

Bu olay oturumları, verileri depolamak için halka arabellek hedeflerini kullanır; bu nedenle - arabellek havuzu ve plan önbelleği gibi - eski olaylar aşamalı olur, böylece istediğiniz zaman aralığından etkinlikleri çekemezsiniz.

Örnek

Soruda bu hayali soruyu sordum:

Bugün bellekle ilgili kaç hata oldu?

Bu bilgiyi system_healthoturumdan çekebilecek bir örnek (ve muhtemelen çok verimli değil) sorgusu :

;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;

(Bu örnek, Amit Banerjee'nin system_healthoturumdaki giriş blog gönderisinden gevşekçe ödünç alıyor .)

Genişletilmiş Olaylar hakkında daha fazla bilgi için (belirli verileri sorgulayabileceğiniz birçok örnek dahil), Jonathan Kehayias'ın bu 31 bölümlü blog serisine bakın:

https://www.sqlskills.com/blogs/jonathan/an-xevent-a-day-31-days-of-extended-events/

Hata Günlüğü

SQL Server, varsayılan olarak geçerli artı en son 6 hata günlüğü dosyasını tutar (ancak bunu değiştirebilirsiniz ). Başlangıç ​​bilgileri (kaç tane çekirdek kullanımda olduğu, bellekte kilitlenen sayfaların ayarlanmış olup olmadığı, kimlik doğrulama modu, vb.) Ve ayrıca belgelenebilecek (ve başka bir yerde ele alınmamış) ciddi senaryolar dahil olmak üzere birçok bilgi saklanır. Son örneklerden biri, bir veritabanının çevrimdışına alındığı zaman arayan biriydi. Bunu, metin için en son 7 hata günlüğünün her birini tarayarak belirleyebilirsiniz 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';

Bu son cevabın diğer bazı detaylarını da ele aldım ve ayrıca kara kurbağasında ve resmi belgelerde bazı iyi bilgiler var .

"Hata" grubundan biri hata günlüğünün varsayılan olarak izlemesini sağlar - ve önemli bilgilerin kuyruktan daha hızlı düşmesini sağlayabilir - her başarılı yedekleme mesajıdır. İz bayrağı 3226'yı etkinleştirerek bunların hata günlüğünü gürültü ile doldurmasını engelleyebilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.