İçeriğe geç

SQL Server'da Kilit Yükseltme — Gün Sonu İşi Neden Müşteriyi Bekletti?

İleri 9 dk Sık karşılaşılır

Önce şunu oku: MVCC ve Kilitler — Eski Satır Sürümleri Nerede Yaşar?

30 saniyede özet

SQL Server, tek bir ifade bir tabloda çok fazla satır kilidi aldığında bunları tek bir tablo kilidine çevirir. Böylece dokunulmayan satırlar da kilitlenir. Güncellemeyi eşiğin altında parçalara bölmek, tabloyu başkalarına açık tutar.

Kütüphaneci binlerce kitabı yeniden diziyor. Önce her rafa “meşgul” yazısı asıyor. Bir noktada bu kadar yazıyla uğraşmaktansa bütün salonun kapısına tek bir “kapalı” levhası asıyor.

  1. Bayt: Gün sonu işi bütün hesapların pozisyonunu tek bir UPDATE ile yeniliyor. Tek satır SQL, ne güzel!

  2. Sen: O sırada bir müşteri emir verdi. Pozisyon satırı güncellenemedi, dakikalarca bekledi.

  3. Bayt: Ama gün sonu işi onun hesabına hiç dokunmuyordu!

  4. Bayt: Dokunmuyordu. Peki tabloda kilitli olan neydi?

Satır kilidi, tablo kilidi

SQL Server bir satırı güncellerken o satırı kilitler; başka biri aynı satırı aynı anda değiştiremez. Diğer satırlar serbesttir.

Ama her kilit bellekte yer tutar. Tek bir ifade bir tabloda çok fazla kilit aldığında, SQL Server bunları tek bir tablo kilidine çevirir. Buna lock escalationSQL Server'ın, tek bir işlemin tuttuğu çok sayıda satır ya da sayfa kilidini daha az sayıda tablo kilidine çevirmesi. Bellek kazandırır, eşzamanlılığı azaltır.Sözlükte gör → denir.

Kafam karıştı, daha basit anlat

Az satırda satır kilitlenir. Çok satırda bütün tablo kilitlenebilir.

Hızlı kontrolBaşlangıç

SQL Server bir satırı güncellerken ne kilitler?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Kilit yükseltme nedir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Dokunmadığın satırlar da kilitli

Gün sonu işi tek bir UPDATE ile 12.000 satır güncelliyor. İş sürerken bir müşterinin emri, bu 12.000 satırın içinde olmayan bir satırı güncellemek istiyor. Bekler mi? Cevabı göster

Bekler. 12.000 satır kilidi yükseltme eşiğini aşar ve satır kilitleri tek bir tablo kilidine çevrilir. Müşterinin satırı işin içinde değildir, ama tablo kilitlidir; iş bitene kadar bekler.

Küçük parçalar: salon açık kalır.
Adım adım oku
  1. Binlerce kitap yeniden diziliyor.
  2. Çok fazla raf: bütün salon kapandı.
  3. Tek kitap isteyen kapıda bekliyor.
  4. Küçük parçalar: salon açık kalır.

Çözüm, büyük güncellemeyi eşiğin altında kalan parçalara bölmektir. Her parça kendi satırlarını kilitler, işini yapar ve onaylanır. Tablo hiç kilitlenmez; müşterinin satırı serbest kalır.

Kafam karıştı, daha basit anlat

Büyük güncellemeyi küçük parçalara böl ve her parçayı ayrı onayla.

Hızlı kontrolOrta

Tek UPDATE 12.000 satırı güncellerken başka bir satırı güncellemek isteyen müşteri neden bekler?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Büyük bir güncellemenin kilit yükseltmesini önlemenin yaygın yolu nedir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

NOLOCK bir çözüm değil

Bekleyen sorgular için akla ilk gelen WITH (NOLOCK) olur. Okuyucu artık beklemez, ama kilitsiz okuduğu için yarım kalmış değişiklikleri görebilir. Sayfalar okunurken yer değiştirirse aynı satırı iki kez sayabilir ya da hiç göremez.

Okuyucuların yazanları beklememesi için daha güvenli yol, veritabanında satır sürümlemeSQL Server'da READ_COMMITTED_SNAPSHOT: okuyucu, yazanı beklemek yerine satırın onaylanmış son sürümünü okur. Yarım veriyi görmez.Sözlükte gör → açmaktır. Okuyucu, onaylanmış son sürümü görür; yazanı beklemez, yarım veriyi de görmez.

Kafam karıştı, daha basit anlat

NOLOCK yarım ve hatalı veri okutabilir. Okuyucular için satır sürümlemeyi kullan.

Hızlı kontrolOrta

NOLOCK ile okumanın riski nedir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Kendin gör

Gün sonu işi pozisyon tablosunu güncelliyor

Tohum 414688

positions tablosu

○ kilit yok

Müşteri emri: · henüz gelmedi

Hız
Adım 0

Şu an ne oldu?

Kilit yok

Müşterinin satırı bu işin içinde değil. Yine de bekleyecek mi?

Görevler0/2

  • Müşteri, dokunulmayan satırı için beklesinaçık

    İpucu

    Tek bir büyük UPDATE.

  • Gün sonu işi bitsin, müşteri hiç beklemesinaçık

    İpucu

    Parçalara böl.

Olay günlüğü (0)

Henüz olay yok. Oynat veya adımla.

  1. Varsayılanla oynat. Tek UPDATE tablo kilidine yükseldi; müşteri, işi bitene kadar iki tur bekledi.
  2. “4.000 satırlık üç parça”yı seç. Her parça eşiğin altında kaldı; müşteri geldiği anda güncelledi.
Hızlı kontrolOrta

Simülatörde "4.000 satırlık üç parça" neden müşteriyi hiç bekletmedi?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Tuzaklar

Yarım kalan iş. Parçalara bölünen iş ortada kesilirse, bazı satırlar güncellenmiş, bazıları güncellenmemiş olur. İşi kaldığı yerden devam edebilecek şekilde yaz: hangi satırların bittiği belli olsun.

Yükseltmeyi kapatmak. Bir tablo için yükseltmeyi kapatmak mümkündür. Ama o zaman sunucu milyonlarca satır kilidi tutmak zorunda kalabilir ve belleği zorlanır; bunu ölçmeden yapma.

İndekssiz WHERE. Güncellemenin WHERE koşulu bir indeksle desteklenmiyorsa, SQL Server satırları bulmak için çok daha fazlasını tarar ve kilitler. Parçalama, iyi bir indeksle birlikte işe yarar.

Kafam karıştı, daha basit anlat

Parçalı işi kaldığı yerden sürdürülebilir yaz. Yükseltmeyi ölçmeden kapatma. WHERE’i indeksle destekle.

Hızlı kontrolOrta

Parçalı gün sonu işi üçüncü parçada kesildi. Yeniden başlatınca ne olmalı?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Aşağıda gün sonu işinin parçalara bölünmüş hâli var: her döngüde en fazla 4.000 satır güncellenir ve onaylanır.

Derinleş · Gün sonu: pozisyon güncellemesi parça parça 3 dosya · ~35 satır · ilk okumada atlayabilirsin
Proje dosyaları

db/end-of-day/ revalue-positions-batch.sql SQL: her turda en fazla 4.000 satır; işlenen satır işaretlenir, iş kaldığı yerden sürer. Parametreler sırayla iş günü tarihidir.

db/end-of-day/revalue-positions-batch.sql
-- One batch: at most 4,000 rows, below the escalation threshold.
UPDATE TOP (4000) p
SET p.market_value = p.quantity * c.close_price,
p.revalued_on = ?
FROM position AS p
JOIN closing_price AS c ON c.isin = p.isin AND c.price_date = ?
WHERE p.revalued_on < ?; -- rows already done are skipped, so a restart resumes

eod/src/main/java/com/bank/eod/ EndOfDayJob.java EndOfDayJob: her parçayı ayrı bir transaction'da çalıştırır; hiç satır kalmayınca durur.

eod/src/main/java/com/bank/eod/EndOfDayJob.java
package com.bank.eod;
import java.time.LocalDate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.support.TransactionTemplate;
public final class EndOfDayJob {
private final JdbcTemplate jdbc;
private final TransactionTemplate tx;
private final String batchSql;
public EndOfDayJob(JdbcTemplate jdbc, TransactionTemplate tx, String batchSql) {
this.jdbc = jdbc;
this.tx = tx;
this.batchSql = batchSql;
}
public void revalue(LocalDate businessDate) {
int updated;
do {
// Each batch commits on its own: its row locks are released before the next one.
updated = tx.execute(status -> jdbc.update(batchSql, businessDate, businessDate, businessDate));
} while (updated > 0);
}
}

db/setup/ readers-use-row-versions.sql Okuyucular için: veritabanında satır sürümleme açık; NOLOCK kullanılmaz.

db/setup/readers-use-row-versions.sql
-- Readers see the last committed version instead of waiting for writers.
ALTER DATABASE Custody SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE;

Kendini sına

Şimşek turu1/4

SQL Server çok fazla satır kilidini tek bir tablo kilidine çevirebilir.

Soru 1/3İleri

Bir tablo için kilit yükseltmeyi tamamen kapatmanın riski nedir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Aklında kalacak üç şey

  1. 1 Tek bir ifade bir tabloda çok fazla kilit alınca SQL Server satır kilitlerini tek bir tablo kilidine yükseltir. Artık dokunulmayan satırlar da kilitlidir.
  2. 2 Büyük bir güncellemeyi eşiğin altında kalan parçalara bölüp her parçayı ayrı onaylamak, yükseltmeyi önler ve başkalarının işini akıtır.
  3. 3 NOLOCK beklemeyi bitirir ama okunanı bozar: yarım kalmış, iki kez sayılmış ya da hiç sayılmamış satırlar okunabilir. Okuyucular için daha güvenli yol satır sürümlemedir.
0/4 kart bu dersten toplandı