← Back to list

SQL Server’da Kriz Yönetimi: Uygulamalı Performans Optimizasyonu (Bölüm 2)

Bir önceki yazımızda [SQL Server’da Performansın Anatomisi: Page Yapısından TempDB Çekişmesine Teknik Bir Yolculuk]…

tugcedokgozss · 2026-02-14 12:57 · 0 claps · 2.6 min read
#ms-sql-server #pages #tempdb #transaction-log #vlf
Open on Medium ↗

SQL Server’da Kriz Yönetimi: Uygulamalı Performans Optimizasyonu (Bölüm 2)

Bir önceki yazımızda [SQL Server’da Performansın Anatomisi: Page Yapısından TempDB Çekişmesine Teknik Bir Yolculuk] https://medium.com/%40tugcedokgoz19/sql-serverda-performans%C4%B1n-anatomisi-page-yap%C4%B1s%C4%B1ndan-tempdb-%C3%A7eki%C5%9Fmesine-teknik-bir-yolculuk-a8beb9ef27b6 başlığıyla işin teorik mutfağına girmiştik. Şimdi o bilgileri kuşanıp, kilitlenen bir sistemi ayağa kaldıracağız.

Hazırsanız, SQL Server Management Studio (SSMS) ekranlarını açalım ve simülasyona başlayalım.

Senaryo: Büyük İndirim Günü ve Sistem Çöküşü

Şirketin mobil uygulaması üzerinden saniyede 10.000 kişi aynı anda “Sepete Ekle” butonuna basıyor. İlk 5 dakika her şey yolunda görünürken birden Dashboard kızıla boyanıyor. Müşteriler “Ödeme tamamlanamadı” hatası alıyor, raporlar çekilemiyor ve CPU kullanımı %100'de çakılı kalıyor.

Gelin bu kaosu adım adım simüle edelim ve çözelim.

  1. Sorun: Pages & Extents (Deponun İç Yapısı)

Müşteriler ürün aratırken disk kullanımı %100’e vuruyor. Çünkü indeksler düzgün değil ve SQL Server 850.750'nci kaydı bulmak için 1 milyon satırı tek tek okuyor.

1. Adım: Deney Alanını Hazırlama

Önce test yapacağımız veri tabanını ve “indekssiz” (yani deponun darmadağın olduğu) ana tablomuzu oluşturalım.

`-- 1. Temiz bir başlangıç
CREATE DATABASE ETicaretTest;
GO
USE ETicaretTest;
GO

-- 2. Katalogsuz (İndekssiz) Tablo Oluşturma
CREATE TABLE Satisler(
    SatisId INT,
    MusteriAd NVARCHAR(50),
    UrunBarkod NVARCHAR(50),
    IslemTarihi DATETIME
);
GO

-- 3. 1 Milyon Satır "Yük" Bindirme (Simülasyon)
SET NOCOUNT ON;
DECLARE @i INT = 1;
WHILE @i <= 1000000
BEGIN
    INSERT INTO Satisler (SatisId, MusteriAd, UrunBarkod, IslemTarihi)
    VALUES(@i, 'Musteri' + CAST(@i AS VARCHAR), 'BARKOD-' + CAST(@i AS VARCHAR), GETDATE());
    SET @i = @i + 1;
END;
PRINT '1 Milyon satır başarı ile eklendi';

2. Adım: “Table Scan” Faciası ve Müdahale

Kriz: Bir müşteri 850.750 ID’li siparişini sorguluyor. Veri tabanı bu kaydı bulmak için tüm depoyu (1 milyon satırı) tek tek gezmek zorunda kalıyor.

Kodla Analiz Et:

`-- CTRL + M (Execution Plan) açarak çalıştırın
SELECT * FROM Satislar WHERE SatisID = 850750;

Sonuç: Artık SQL Server depoda nereye gideceğini biliyor. Okunan satır sayısı 1.000.000'dan 1'e düştü!

Gözlem: Execution Plan’da devasa bir “Table Scan” göreceksiniz. SQL Server, 1 satırı bulmak için 1 milyon satırı (binlerce 8KB’lık sayfayı) RAM’e çekti.

Uzman Müdahalesi (Çözüm): Sayfaları fiziksel olarak düzene sokalım.

`CREATE CLUSTERED INDEX IX_SatisID ON Satislar(SatisID);

Sonuç: Artık SQL Server depoda nereye gideceğini biliyor. Okunan satır sayısı 1.000.000'dan 1'e düştü!

3. Adım: Transaction Log (VLF) Kaosu

Kriz: Satışlar o kadar hızlı ki, log dosyasının otomatik büyüme ayarı (1 MB) sistemi kilitliyor. Her 1 MB’da bir SQL Server duruyor, işletim sisteminden yer istiyor ve binlerce minik VLF (sanal günlük) oluşturuyor.

Mevcut Durumu Gör:

`DBCC LOGINFO; -- VLF listesini döker. Eğer yüzlerce satır varsa, prangalar takılmıştır.

Uzman Müdahalesi (Çözüm): Log dosyasını temizleyip, tek seferde büyük ve sağlıklı bir blok olarak açıyoruz.

`-- Önce logu sıfırla (Shrink)
DBCC SHRINKFILE (N'ETicaretTest_log' , 0, TRUNCATEONLY);
GO

-- Şimdi profesyonelce büyüt (Örn: 1GB başlangıç, 512MB büyüme)
ALTER DATABASE ETicaretTest 
MODIFY FILE ( NAME = N'ETicaretTest_log', SIZE = 1024MB , FILEGROWTH = 512MB );
GO

Sonuç: Yazma hızı 5 kat arttı çünkü artık binlerce küçük VLF yerine 10 tane büyük, düzenli VLF var.

4. Adım: TempDB Contention (Mutfaktaki Kavga)

Kriz: 16 çekirdekli canavar gibi bir sunucun var ama TempDB sadece tek bir dosyadan oluşuyor. 16 işlemci de aynı anda o tek dosyaya yazmak için PFS ve GAM sayfaları üzerinde kavga ediyor.

Mevcut Mutfak Tezgahlarını Gör:

`USE tempdb;
EXEC sp_helpfile;

Uzman Müdahalesi (Çözüm): İşlemci çekirdek sayısı kadar (altın kural: max 8) TempDB dosyası oluşturuyoruz.

`USE [master];
GO
ALTER DATABASE [tempdb] ADD FILE (  
    NAME = N'tempdev2',  
    FILENAME = N'C:\Program Files\...\tempdb_msi_2.ndf',  
    SIZE = 100MB ,  
    FILEGROWTH = 64MB  
);
GO

Sonuç: Her çekirdeğin artık kendi “çalışma alanı” var. Kuyruk bitti, raporlar saniyeler içinde gelmeye başladı.

Savaşın Sonu: Ne Başardık?

Pages: İndeks kullanarak diske olan gereksiz “eğilip kalkma” (I/O) sayısını bitirdik.

VLF: Log yönetimini optimize ederek yazma hızındaki “darboğazı” ortadan kaldırdık.

TempDB: Çoklu dosya yapısıyla işlemci çekirdeklerini birbirine düşürmekten kurtardık.

Veri tabanı sadece veri saklamak değil, o veriye en verimli şekilde ulaşma sanatıdır. Bir sonraki yazıda görüşmek üzere!


메타데이터
post_id
3cf67c8d3972
slug
sql-serverda-kriz-yönetimi-uygulamalı-performans-optimizasyonu-bölüm-2-3cf67c8d3972
url
https://medium.com/@tugcedokgoz/sql-serverda-kriz-y%C3%B6netimi-uygulamal%C4%B1-performans-optimizasyonu-b%C3%B6l%C3%BCm-2-3cf67c8d3972
canonical_url
https://medium.com/@tugcedokgoz/sql-serverda-kriz-y%C3%B6netimi-uygulamal%C4%B1-performans-optimizasyonu-b%C3%B6l%C3%BCm-2-3cf67c8d3972
author_url
https://medium.com/@tugcedokgoz
status
ok
fetched_at
2026-07-14 19:34:30