SQL Server Error Log’larını Düzenleyip Tabloya Yazma: Tüm Log Tek Satırda
For the English version of this article, click here.
SQL Server Error Log’larını Düzenleyip Tabloya Yazma: Tüm Log Tek Satırda
For the English version of this article, click here.
SQL Server, instance üzerinde gerçekleşen hata ve uyarıları error log dosyalarına yazar. Ancak bu log’ları okumak her zaman pratik değildir: SSMS üzerinden açmak yavaş olabilir ve filtreleme imkânı sınırlıdır. Bu makalede, kendi çalıştığım ortamlarda aktif bir şekilde kullandığım, kritik error log kayıtlarını düzenli bir şekilde tabloya aktaran ve bunu otomatize eden bir yapıdan bahsedeceğim. Sistem hazır olduğunda aşağıdaki gibi bir tablomuz hazır olacak.

Bu arada “Error log’larını yakalamak için Extended Events gibi daha güçlü seçeneklerimiz de mevcut elbette; fakat xp_readerrorlog ile bu yapıyı kurmak çok daha hızlı ve pratik — ekstra bir session tanımlamak, event file yönetmek ya da storage planlamak gerekmez. Error log'larındaki kritik hataları yakalamak için ayrı bir XE session açmak ve yönetmek, bu işin karmaşıklığını gereksiz yere artırır. Extended Events'i, log'da yakalanamayan daha ayrıntılı olayları izlemek istediğinizde devreye almak daha mantıklı."
Neden Bir Tabloya Taşıyalım?
SQL Server’ın error log mekanizması güçlüdür; ancak ham haliyle kullanımı biraz verimsizdir. Log dosyaları instance yeniden başlatıldığında ya da sp_cycle_errorlog çalıştırıldığında rotate edilir ve belirli bir tarihten sonraki log'lara erişilemez. Ayrıca log içindeki her hata kaydı, birden fazla satırdan oluşabilir — bu da parse etmeyi zorlaştırır.
Kritik hataları (severity bilgisi içeren satırları) bir tabloya taşıdığımızda şu avantajları elde ederiz:
- Zaman aralığına göre hızlı sorgulama
ErrorNumber,Severity,Stategibi alanlar üzerinde filtreleme- Uzun vadeli geçmiş saklama (rotation’dan bağımsız)
- Alerting ve raporlama için temel oluşturma
Asıl Problem: İki Satır, Tek Hata
Aşağıdaki ekran görüntüsü SQL Server Management Studio’nun Log File Viewer’ından alınmıştır:

Görüntüde dikkat çeken şey şu: 7/11/2026 5:43:26 PM tarihli iki satıra bakın.
- 1. satır →
The query processor ran out of internal resources and could not produce a query plan. - 2. satır →
Error: 8623, Severity: 16, State: 1.
Bu iki satır aynı hataya ait. Biri hatanın açıklamasını, diğeri yapısal bilgilerini (ErrorNumber, Severity, State) taşıyor. Aynı timestamp, aynı spid — ama Log File Viewer'da birbirinden bağımsız iki kayıt olarak görünüyor.
Şimdi bunu olduğu gibi bir tabloya yazdığınızı düşünün. Binlerce satır arasında hangi açıklama hangi error number ile ilişkili? Timestamp’ler aynı olduğunda bile spid çakışmaları ve sıralama farklılıkları bu eşleştirmeyi güvenilmez hale getirir.
sp_ErrorLog'un temel çözdüğü problem tam olarak bu: her iki satırı okuyup tek bir kayıt olarak tabloya yazmak.
Genel Mimari
Yapı üç bileşenden oluşuyor:
- Hedef database — Log kayıtlarının tutulacağı yer (
_DBAPERFya da mevcut bir monitoring database'i) - Stored procedure — Log’ları okuyup parse eden ve tabloya yazan
sp_ErrorLog - SQL Server Agent Job — Procedure’ü periyodik olarak tetikleyen otomasyon katmanı
Adım 1: Hedef Tabloyu Oluşturma
Önce log kayıtlarının yazılacağı tabloyu oluşturuyoruz. Bu tabloyu, daha önce oluşturulmuş ya da ayrıca açılacak bir monitoring database’i içinde konumlandırabilirsiniz.
USE [_DBAPERF]
GO
CREATE TABLE [dbo].[ErrorLog](
[LogTime] [datetime2](3) NOT NULL,
[ErrorMessage] [nvarchar] (max) NOT NULL,
[ErrorNumber] [int] NOT NULL,
[Severity] [int] NOT NULL,
[State] [int] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER AUTHORIZATION ON [dbo].[ErrorLog] TO SCHEMA OWNER
Kolon yapısına bakıldığında:
LogTime— Hatanın log'a düştüğü zaman damgası (milisaniye hassasiyetiyle)ErrorMessage— Ham log satırının parse edilmiş tam metniErrorNumber,Severity,State— Error log satırı içinden ayrıştırılan yapısal bilgiler
Adım 2: Stored Procedure Oluşturma
sp_ErrorLog procedure'ü dört temel işi yapar: log'ları okur, severity içeren satırları tespit eder, iki satırı birleştirir ve tabloya yazar.
USE [_DBAPERF]
GO
CREATE PROCEDURE [dbo].[sp_ErrorLog]
AS
BEGIN
SET NOCOUNT ON;
DECLARE @logno INT = 0; -- 0: Current Log File
DECLARE @logFileType SMALLINT = 1; -- 1: Server Log, 2: Agent Log
DECLARE @start DATETIME;
DECLARE @end DATETIME;
DECLARE @ErrorLog TABLE (
RowNum INT IDENTITY(1,1),
LogDateTime NVARCHAR(50),
ProcessInfo NVARCHAR(100),
ErrorMessage NVARCHAR(MAX)
);
-- Son 10 dakikayı tara
SET @start = DATEADD(MINUTE, -10, GETDATE());
SET @end = GETDATE();
DECLARE @searchString1 NVARCHAR(256) = '';
DECLARE @searchString2 NVARCHAR(256) = '';
-- Log kayıtlarını table değişkene al
INSERT INTO @ErrorLog (LogDateTime, ProcessInfo, ErrorMessage)
EXEC xp_readerrorlog @logno, @logFileType,
@searchString1, @searchString2,
@start, @end;
DROP TABLE IF EXISTS #err;
-- Severity içeren satırları bul, bir sonraki satırla birleştir
SELECT DISTINCT
TRY_CAST(e1.LogDateTime AS DATETIME2(3)) AS LogDateTime,
e1.ErrorMessage + ' ' + ISNULL(e2.ErrorMessage, '') AS ErrorMessage
INTO #err
FROM @ErrorLog e1
LEFT JOIN @ErrorLog e2 ON e2.RowNum = e1.RowNum + 1
WHERE LOWER(e1.ErrorMessage) LIKE '%severity%';
-- Parse edip hedef tabloya yaz
INSERT INTO [_DBAPERF].[dbo].[ErrorLog]
SELECT
LogDateTime,
ErrorMessage,
-- Error number
TRY_CAST(
LTRIM(RTRIM(
SUBSTRING(
ErrorMessage,
CHARINDEX('Error:', ErrorMessage) + 6,
CHARINDEX(',', ErrorMessage)
- CHARINDEX('Error:', ErrorMessage) - 6
)
)) AS INT
) AS ErrorNumber,
-- Severity
TRY_CAST(
LTRIM(RTRIM(
SUBSTRING(
ErrorMessage,
CHARINDEX('Severity:', ErrorMessage) + 9,
CHARINDEX(',', ErrorMessage, CHARINDEX('Severity:', ErrorMessage))
- CHARINDEX('Severity:', ErrorMessage) - 9
)
)) AS INT
) AS Severity,
-- State
TRY_CAST(
LTRIM(RTRIM(
SUBSTRING(
ErrorMessage,
CHARINDEX('State:', ErrorMessage) + 6,
CHARINDEX('.', ErrorMessage + '.', CHARINDEX('State:', ErrorMessage))
- CHARINDEX('State:', ErrorMessage) - 6
)
)) AS INT
) AS State
FROM #err
ORDER BY LogDateTime DESC;
-- 180 günden eski kayıtları temizle
DELETE FROM [_DBAPERF].[dbo].[ErrorLog]
WHERE LogTime < DATEADD(DAY, -180, GETDATE());
END
GO
İki Satırın Birleştirilmesi — Temel Mantık
SQL Server’ın error log yapısında dikkat çeken bir nokta var: severity bilgisi içeren bir hata her zaman iki ardışık satır olarak gelir. İlk satır error numarası, severity ve state bilgilerini taşır; ikinci satır ise hatanın açıklama metnini içerir.
Bu yapıdan faydalanmak için @ErrorLog table variable'ına IDENTITY ile sıra numarası ekliyoruz. Ardından RowNum + 1 ile self join yaparak iki satırı tek bir kayıtta birleştiriyoruz:
FROM @ErrorLog e1
LEFT JOIN @ErrorLog e2 ON e2.RowNum = e1.RowNum + 1
WHERE LOWER(e1.ErrorMessage) LIKE '%severity%'
String Parsing ile Yapısal Alan Çıkarma
Ham error log satırı şu formatta gelir:
Error: 18456, Severity: 14, State: 8. Login failed for user 'sa'.
CHARINDEX ve SUBSTRING kombinasyonuyla ErrorNumber, Severity ve State değerlerini bu metinden ayrıştırıyoruz. TRY_CAST kullanmak önemli — beklenmedik bir format geldiğinde procedure hata fırlatmak yerine NULL döndürür ve çalışmaya devam eder.
Retention Yönetimi
Procedure’ün sonundaki DELETE bloğu, 180 günden eski kayıtları otomatik olarak temizler. Bu sayede tablo süresiz büyümez ve ayrı bir temizlik job'ı yazmanıza gerek kalmaz.
Adım 3: SQL Server Agent Job ile Otomatizasyon
Procedure’ü manuel çalıştırmak yeterli değil. Bunu 10 dakikada bir tetikleyecek bir SQL Server Agent Job oluşturuyoruz.
SSMS üzerinden:
- SQL Server Agent → Jobs → New Job
- General sekmesinde job’a bir isim verin: örneğin
DBA - Collect Error Logs - Steps sekmesinde yeni bir step ekleyin:
- Type:
Transact-SQL script (T-SQL) - Database:
_DBAPERF - Command:
EXEC [dbo].[sp_ErrorLog];
- Schedules sekmesinde yeni bir schedule oluşturun:
- Frequency:
Daily - Occurs every:
10 minutes - Start time:
00:00:00
Job kaydedildikten sonra bir kez Start Job at Step ile manuel test yapmanızı öneririm.
Sonuç
Bu yapı sayesinde SQL Server error log’ları artık ham metin dosyalarında kaybolmuyor; her 10 dakikada bir parse edilerek sorgulanabilir bir tabloya aktarılıyor. ErrorNumber, Severity ve State kolonları üzerinden kolayca filtreleme yapabilir, belirli hata kodlarına göre alert mekanizmaları kurabilir ya da Grafana, Power BI gibi araçlara bağlayarak dashboard oluşturabilirsiniz. Database Mail kullanarak burada dilediğiniz bir filtreleme ile ciddi durumlarda mail attırabilirsiniz.
메타데이터
- post_id
- b2d8da1271b8
- slug
- sql-server-error-loglarını-düzenleyip-tabloya-yazma-tüm-log-tek-satırda-b2d8da1271b8
- url
- https://medium.com/@ufuk-gokdemir/sql-server-error-loglar%C4%B1n%C4%B1-d%C3%BCzenleyip-tabloya-yazma-t%C3%BCm-log-tek-sat%C4%B1rda-b2d8da1271b8
- canonical_url
- https://medium.com/@ufuk-gokdemir/sql-server-error-loglar%C4%B1n%C4%B1-d%C3%BCzenleyip-tabloya-yazma-t%C3%BCm-log-tek-sat%C4%B1rda-b2d8da1271b8
- author_url
- https://medium.com/@ufuk-gokdemir
- status
- ok
- fetched_at
- 2026-07-16 18:45:13