Optimized Locking Nedir? SQL Server 2025’te Devrim


1. Başlangıç

Önceki makalelerde SQL Server 2025’in vector search ve native JSON tarafındaki yeniliklerini ele almıştım. Bu hafta üzerinde duracağımız konu, ekran karartan keyword bulutlarına henüz fazla girmedi ama production’da en çok fark yaratacak özelliklerinden biri: Optimized Locking. DBA olarak günlük hayatınızda lock escalation, blocking chain, deadlock graph okumakla zaman geçiriyorsanız bu yazı tam size göre.

Optimized Locking, transaction lock mekanizmasını köklü şekilde değiştiriyor. Microsoft 2023’te Azure SQL Database tarafında konuyu duyurmuştu, SQL Server 2025 (17.x) ile artık on-prem tarafa da geldi. Amacım bu yazıda özelliği teorik olarak anlatmaktan çok kendi laboratuvarınızda çalıştırıp lock sayılarındaki, blocking ve deadlock davranışındaki farkları sys.dm_tran_locks ve extended event’ler üzerinde gözlemenizi sağlamak.

Bunun için üç workshop hazırladım. Workshop 1’de klasik kilitleme ile optimized kilitlemenin lock sayılarını ve lock memory tüketimini yan yana göreceğiz. Workshop 2’de LAQ’ın yan etkisini iki ayrı session ile reprodüce edeceğiz; ek olarak predicate requalification mekanizmasını da izleyeceğiz. Workshop 3’te ise optimized locking aktifken deadlock üretebilen bir senaryoyu kurup yeni TID-bazlı deadlock report’unu okuyacağız.

Yazı boyunca ‘optimized locking’ demek için OL kısaltmasını kullanacağım. Microsoft dokümanı tam adı kullanıyor ama her paragrafta tam adı geçirmek okumayı ağırlaştırıyor; biz pratiğe yakın duralım.

2. Optimized Locking Nedir? — Üç Bileşen

Optimized Locking aslında üç ayrı mekanizmanın birleşimi: Transaction ID (TID) Locking, Lock After Qualification (LAQ) ve Skip Index Locks (SIL). Microsoft dokümanı genelde ilk ikisini öne çıkarıyor ama SIL üçüncü ve etkili bir parça, biz üçünü de inceleyeceğiz.

Klasik kilitleme mantığı şöyle çalışır: bir UPDATE 1000 satır günceliyorsa engine, 1000 ayrı X (exclusive) row lock’ı transaction sonuna kadar tutar. Aynı sayfada 16 satır olduğunu varsayarsak ortalama 62 IX page lock’ı da transaction boyu açık kalır. Buna tablonun kendisi ve clustered index üzerinde IX lock’ları eklenince bin küsür lock object kolayca birikir. Her lock object yaklaşık 100 byte. Bunu binlerce satıra ve onlarca eş zamanlı transaction’a çarptığımızda lock memory ciddi bir kaynağa dönüşür ve lock escalation kaçınılmazlaşır.

Optimized Locking bu hikayeyi şöyle kırıyor: lock’ın sahibi ‘satır’ veya ‘sayfa’ değil, ‘transaction’ın kendisi’ oluyor. Transaction’a unique bir kimlik (TID) veriliyor, satırlar bu TID ile damgalanıyor, ve transaction sonuna kadar tutulan tek lock TID üzerinde olan X lock oluyor. Row ve page lock’lar yine alınıyor ama her satır işlenip TID damgası basıldıktan sonra hemen bırakılıyor. Memory tarafında ciddi bir kazanç, lock escalation tarafında neredeyse yok denecek kadar düşük bir olasılık.

3. TID Locking

TID locking nasıl çalışıyor adım adım bakalım. Aşağıdaki flowchart, bir UPDATE’in motor tarafında izlediği yolu gösteriyor. Dikkatinizi çeken şey, transaction boyu kalan tek lock’ın TID üzerindeki X lock olması olmalı, geri kalan row/page lock’lar geçici.

Şekil 1 — TID locking iç işleyişi. Row/page lock’lar her satırda alınır, hemen bırakılır; sadece TID lock transaction sonuna kadar tutulur.

Burada iki kritik nokta var. Birincisi: row ve page lock’ların hâlâ alınıyor olması ACID semantiğini koruyor. Aynı satıra başka bir transaction yazmaya kalkarsa kısa süreli lock’lar onu bekleterek tutarlı sonuç garanti ediyor. İkincisi: lock escalation eşiği olan 5000 lock’a ulaşmak artık çok zor, çünkü row lock’lar anında bırakılıyor.

Bir başka kazanım deadlock tarafında. Deadlock’ların büyük kısmı, iki transaction’ın row/page kilitlerini farklı sırada alıp birbirini beklemesinden kaynaklanır. Row lock’lar transaction boyu tutulmadığı için bu kategori büyük oranda eriyor. Tamamen ortadan kalkmıyor tabii; iki transaction TID’leri üzerinde S/X lock’lar üzerinden hâlâ deadlock yaratabilir. Workshop 3’te bu senaryoyu üreteceğiz.

4. Lock After Qualification (LAQ) — Akıllı Predicate Değerlendirmesi

LAQ, Optimized Locking’nin ikinci ve belki en zarif parçası. Klasik mekanizmada bir UPDATE’in WHERE predikatı satır kilitlendikten sonra değerlendirilirdi: önce U (update) lock al, satırı tut, sonra predicate’e bak, uyuyorsa X lock’a yükselt. LAQ bu sırayı tersine çeviriyor: önce satırın son commit edilmiş versiyonu üzerinde predicate’i değerlendir, uymuyorsa kilit alma, uyuyorsa kilitle ve güncelle.

Pratikte bu, gereksiz beklemenin önüne geçen bir optimizasyon. Eskiden bir UPDATE komutu, kendi WHERE’iyle hiç ilgilenmediği satırlar için bile geçici U lock alırdı; LAQ ile bu satırlar artık kilitlenmiyor bile. Aşağıdaki akış diyagramı, LAQ’ın motor içindeki karar ağacını gösteriyor. Üç dallanma noktasına dikkat edin: predicate sağlandı mı, başka aktif transaction var mı, satır beklediğimizden farklı mı değişti.

LAQ predicate evaluation akışı. Operatör predicate requalification desteklemiyorsa motor statement’ı abort edip LAQ’sız restart ediyor.

Diyagramın sağ alt köşesindeki abort/restart yolu önemli. LAQ’ın çalışabilmesi için query operatörlerinin ‘predicate requalification’ özelliğini desteklemesi gerekiyor, yani satır beklediğimizden farklı bir biçimde değişmişse predicate’i tekrar değerlendirebilmesi. Tüm operatörler bunu desteklemiyor. Desteklemeyen bir plan kullanılıyorsa engine statement’ı abort edip LAQ olmadan yeniden başlatıyor. Bu olduğunda lock_after_qual_stmt_abort isimli extended event tetikleniyor; tracelersek ölçebiliyoruz.

Dahası, sürekli abort olan workload’larda OL bunu tespit edip LAQ’ı geçici olarak devre dışı bırakıyor. Microsoft buna ‘LAQ heuristics feedback’ diyor: engine ‘potansiyel boşa harcanan iş’ (logical reads cinsinden) ile toplam iş arasındaki oranı izliyor; eşik aşılırsa LAQ’ı kapatıyor, oranlar normale dönerse tekrar açıyor. Yani LAQ tamamen deterministik değil, workload’unuza göre kendini kalibre ediyor, bu detayı bilen az DBA tanıyorum.

İki istisna durumu daha var: değişken atayan UPDATE’ler (UPDATE … SET @var = … gibi) ve OUTPUT clause kullanan statement’lar abort/restart edilemiyor çünkü semantik değişir. Bu iki desende LAQ baştan devre dışı.

5. Skip Index Locks (SIL) — Üçüncü Optimizasyon

Microsoft dokümanlarında en az ses getiren parça SIL. RCSI ve LAQ aktifken, bir satıra yazarken aslında row ve page lock’larına gerek olmayabilir , çünkü aynı satırı stable bir biçimde okumayı bekleyen başka bir RLQ (row locking query) yoksa, kısa süreli X row lock + IX page lock zincirini tamamen atlamak ve sadece exclusive page latch ile geçmek mümkün. SIL bunu yapıyor.

RLQ dediğimiz şey REPEATABLE READ veya SERIALIZABLE isolation level’ında çalışan ya da ilgili lock hint’leri kullanan sorgular. Bunlar yoksa motor row/page lock’ı atlıyor ve performansı bir tık daha yukarı çekiyor. Özellikle binlerce satırı güncelleyen toplu işlerde bu fark hissediliyor.

SIL’in şu anda devreye girdiği durumlar:

  • Heap’lere yapılan INSERT’lerde IX page lock’ları atlanır.
  • Clustered index, nonclustered index ve heap’lerde yapılan UPDATE’lerde IX page ve X row lock’ları atlanır.

SIL şu durumlarda devreye girmiyor:

  • DELETE statement’ları.
  • Heap üzerindeki UPDATE’ler eğer satırda forwarding pointer varsa veya update yeni forwarding pointer ekliyorsa.
  • Satır LOB tipinde bir kolon içeriyorsa: varchar(max), nvarchar(max), varbinary(max), ve yeni gelen json data type.
  • Aynı transaction içinde page split yaşamış sayfalardaki satırlar.

Bu sınırlamaları akılda tutmak gerek; özellikle JSON kolonu olan tablolarda OL’nin SIL katmanı devreye giremez. JSON ile ilgili daha geniş incelemeyi sonraki yazıda yapacağız.

6. Sahne Arkasında — ADR ve RCSI Bağımlılıkları

Optimized Locking tek başına aktif edilemiyor, üç ayrı feature’ın üst üste bindiği bir katman. ADR (Accelerated Database Recovery) tabanda. Optimized Locking, ADR aktif olmayan bir database’de açılamaz; tersine, Optimized Locking açıkken ADR’yi kapatamazsınız (önce Optimized Locking’yi kapatmanız lazım). RCSI orta katman: RCSI olmadan da Optimized Locking’yi açabilirsiniz ama LAQ tarafı çalışmaz, sadece TID locking faydası alırsınız. Tam fayda için RCSI şart.

OL, ADR ve RCSI’nin üzerine inşa ediliyor. SIL ise LAQ’ın aktif olmasına bağlı.

Azure SQL Database, Azure SQL MI (Always-up-to-date update policy) ve Microsoft Fabric SQL’de bu üçü zaten default açık. SQL Server 2025’te ise ADR sizin elinizde olabilir, RCSI default kapalı, OL default kapalı. Yani on-prem tarafta üç adımlık bir aktivasyon süreci var.

7. Etkinleştirme ve İzleme — Komut Komut

Önce mevcut durumu kontrol edelim:

SELECT
database_id,
name,
is_accelerated_database_recovery_on AS adr,
is_read_committed_snapshot_on AS rcsi,
is_optimized_locking_on AS optimized_locking
FROM sys.databases
WHERE name = DB_NAME();

Üç sütun da 0 ise sırayla açıyoruz. RCSI, ROLLBACK IMMEDIATE ile aktif bağlantıları kesiyor; bakım penceresinde yapın:

-- 1. ADR aç (varsa atla)
ALTER DATABASE CURRENT
SET ACCELERATED_DATABASE_RECOVERY = ON;
GO
-- 2. RCSI aç (kullanıcılar dışarı çıkmalı)
ALTER DATABASE CURRENT
SET READ_COMMITTED_SNAPSHOT = ON
WITH ROLLBACK IMMEDIATE;
GO
-- 3. Optimized Locking aç
ALTER DATABASE CURRENT
SET OPTIMIZED_LOCKING = ON;
GO

Hızlı doğrulama:

SELECT DATABASEPROPERTYEX(DB_NAME(), 'IsOptimizedLockingOn')
AS is_optimized_locking_enabled;
-- 1 dönerse aktif, 0 ise kapalı, NULL dönerse engine sürümü desteklemiyor.

İzleme için iki yeni extended event’i bilmek faydalı. locking_stats event’i her birkaç dakikada bir database bazında toplu lock istatistiklerini yayınlıyor: lock escalation sayısı, TID ve LAQ aktif mi, LAQ kullanılamayan sorgu sayıları gibi. locking_stats2 event’i SIL ve LAQ heuristics istatistiklerini taşıyor. Aşağıdaki örnek session bunları yakalıyor:

CREATE EVENT SESSION ol_monitor ON SERVER
ADD EVENT sqlserver.locking_stats,
ADD EVENT sqlserver.locking_stats2,
ADD EVENT sqlserver.lock_after_qual_stmt_abort
ADD TARGET package0.event_file
(SET filename = N'OL_Monitor.xel', max_file_size = 50, max_rollover_files = 4);
GO
ALTER EVENT SESSION ol_monitor ON SERVER STATE = START;

Bu session açıkken workload’unuzu birkaç saat çalıştırın, sonra .xel dosyasını Management Studio veya sys.fn_xe_file_target_read_file ile okuyun. lock_after_qual_stmt_abort event’inin sıkça tetiklendiğini görüyorsanız LAQ’sız restart eden sorgularınız var demektir; plan’larını incelemek lazım.

8. Workshop 1 — TID Locking’i Gözle

Şimdi farkı görelim. İki ayrı database üzerinde aynı senaryoyu çalıştıracağız: bir tane OL aktif olmayan database, bir tane aktif. Aynı transaction’ı aç, paralel session’da sys.dm_tran_locks ile lock sayısına bak.

-- Test tablosu
CREATE TABLE dbo.OL_Demo
(
id INT PRIMARY KEY,
val NVARCHAR(50)
);
INSERT INTO dbo.OL_Demo (id, val)
SELECT TOP (1000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
REPLICATE('x', 50)
FROM sys.all_columns;

Session 1 — transaction’ı aç, COMMIT etme:

BEGIN TRANSACTION update_test;
UPDATE dbo.OL_Demo
SET val = REPLICATE('y', 50);
-- COMMIT henüz yok. SPID'i not edin (SELECT @@SPID;).

Session 2 — paralelde lock sayısını ölç:

SELECT
request_session_id,
resource_type,
request_mode,
resource_description,
request_status
FROM sys.dm_tran_locks
WHERE request_session_id = <ÜSTTEKI_SPID>
ORDER BY resource_type;
-- Çıktıyı kaydedin, ardından Session 1'de:
-- COMMIT TRANSACTION update_test;

Lock memory tüketimini ölçmek için sys.dm_os_memory_clerks üzerinden Lock Manager’ı kontrol edebilirsiniz; özellikle yüksek concurrency’de OL kapalı tarafta dramatik bir fark görürsünüz:

SELECT
type,
pages_kb,
virtual_memory_committed_kb
FROM sys.dm_os_memory_clerks
WHERE type IN ('OBJECTSTORE_LOCK_MANAGER', 'OBJECTSTORE_LBSS')
ORDER BY pages_kb DESC;

Aynı 1000 satırlık UPDATE, OL kapalıyken yüzlerce row/page lock; açıkken yalnızca 1 TID (XACT) X lock.

Optimized Locking kapalı tarafta binlerce KEY/PAGE lock satırı görürsünüz. Açık tarafta tek bir XACT (transaction) kaynağı üzerinde X lock, başka bir şey yok, çünkü eski row lock’lar satır güncellenir güncellenmez bırakılmış olur. Lock memory tarafında ciddi nefes aldıran bir değişiklik.

9. Workshop 2 — LAQ’ın Yan Etkisi ve Predicate Requalification

LAQ’ın iki yüzü var: bir tarafta gereksiz beklemeyi keser, diğer tarafta uygulamanın kilit sırasına dayanan bir iş kuralı varsa farklı sonuç üretebilir. Bu detayı production’a açmadan önce mutlaka test ortamında çalıştırın.

CREATE TABLE dbo.t4
(
a INT NOT NULL,
b INT NULL
);
INSERT INTO dbo.t4 VALUES (1, 1);

İki ayrı SSMS penceresi açın. Sırayı tabloda gösterilen şekilde uygulayın:

Session 1 – SSMSSession 2 – SSMS
BEGIN TRANSACTION T1;
UPDATE dbo.t4 SET b = 2 WHERE a = 1;
BEGIN TRANSACTION T2;
UPDATE dbo.t4 SET b = 3 WHERE b = 2;
COMMIT TRANSACTION;
COMMIT TRANSACTION;

Aynı T1/T2 senaryosu LAQ kapalıyken (1,3) sonucu verir, LAQ açıkken (1,2).

LAQ olmadan T2, T1’i bekler. T1 commit edince T2 satırı yeniden değerlendirir, b artık 2 olduğu için predicate sağlanır, b = 3 olur. Sonuç: (1, 3). LAQ ile T2 bekleme yerine en son commit edilmiş versiyonu (b = 1) kullanır, predicate b = 2 sağlanmaz, satır skip edilir. Sonuç: (1, 2).

Şimdi predicate requalification senaryosunu kuralım. Aşağıdaki örnekte iki transaction aynı satırı aynı predicate ile güncellemeye çalışıyor; LAQ’ın requalify yolundaki davranışını göreceksiniz:

CREATE TABLE dbo.t3 (a INT NOT NULL, b INT NULL);
INSERT INTO dbo.t3 VALUES (1, 10), (2, 20), (3, 30);
Session 1 – SSMSSession 2 – SSMS
BEGIN TRANSACTION;
UPDATE dbo.t3 SET b = b + 10 WHERE a = 1;
BEGIN TRANSACTION;
UPDATE dbo.t3 SET b = b + 10 WHERE a = 1;
— Bekler
COMMIT TRANSACTION;
— LAQ requalify: b son commit edilmişe göre 20
— Update uygulanır
COMMIT TRANSACTION;

T2 satırı kilitliyken T1 bitirir, T2 son commit edilmiş versiyonda predicate (a = 1) hâlâ geçerli olduğu için satırı günceller. Bu requalify davranışı; abort/restart olmadan akıllıca tekrar değerlendirme. lock_after_qual_stmt_abort event’i bu senaryoda tetiklenmez çünkü plan’daki operatörler requalification’ı destekliyor.

Eğer plan operatörü destek vermezse abort olur ve event tetiklenir. UPDATE’in OUTPUT clause kullandığı sorgular bu kategoriye girer. Aşağıdaki extended event session’ı ile yakalayabilirsiniz:

CREATE EVENT SESSION laq_aborts ON SERVER
ADD EVENT sqlserver.lock_after_qual_stmt_abort
(ACTION (sqlserver.sql_text, sqlserver.database_id))
ADD TARGET package0.ring_buffer;
GO
ALTER EVENT SESSION laq_aborts ON SERVER STATE = START;

Microsoft, blocking semantiğini kritik şekilde etkilenen sorgular için READCOMMITTEDLOCK table hint’ini öneriyor, ilgili sorguda klasik blocking davranışını geri getirir, Optimized Locking diğer sorgularda devam eder. Hint kullanımı tablo bazında, sorgu bazında değil; yani hint’i koyduğunuz tablo için OL devre dışı kalır, aynı sorgudaki diğer tablolar etkilenmez.

10. Workshop 3 — Optimized Locking Aktifken Deadlock Üretmek

Optimized Locking’nin deadlock’ları büyük oranda azalttığını söylemiştik. ‘Tamamen ortadan kaldırmıyor’ demiştim; gerçekten de iki transaction TID lock’ları üzerinde birbirini bekleyebilir. Şu senaryo Microsoft dokümanında da geçen klasik bir yapı aslında:

CREATE TABLE dbo.t2
(
a INT PRIMARY KEY NOT NULL,
b INT NULL
);
INSERT INTO dbo.t2 VALUES (1, 10), (2, 20), (3, 30);
Session 1 (xactA)Session 2 (xactB)
BEGIN TRANSACTION xactA;
UPDATE dbo.t2 SET b = b + 10 WHERE a = 1;
BEGIN TRANSACTION xactB;
UPDATE dbo.t2 SET b = b + 10 WHERE a = 2;
UPDATE dbo.t2 SET b = b + 100 WHERE a = 2;
— B’nin TID’sini bekler
UPDATE dbo.t2 SET b = b + 20 WHERE a = 1;
— A’nın TID’sini bekler — DEADLOCK

Her session kendi TID’si üzerinde X lock tutuyor, diğerinin TID’si üzerinde S lock istiyor. Engine deadlock’ı tespit edip birini victim seçiyor. Klasik deadlock graph’tan farklı olarak yeni format <resource-list> içinde <xactlock> elementleri içeriyor, TID bazlı bilgileri buradan okursunuz.

Bu senaryoyu reprodüce ettiğinizde sys.dm_tran_locks’ta XACT resource_type’lı lock’lar göreceksiniz; klasik KEY veya PAGE bekleme zincirleri yok. Yeni format’a alışmak için bir kez canlı görmek faydalı.

11. Lock Hint’lerinden Uzak Durun

OL aktifken UPDLOCK, HOLDLOCK, XLOCK, READCOMMITTEDLOCK, REPEATABLEREAD gibi hint’lerin kullanıldığı sorgular özelliğin faydasını ciddi azaltıyor. Engine, hint’in semantiğini saygıyla karşılayıp eski mekanizmaya dönüyor, yani lock’lar transaction sonuna kadar tutuluyor.

Önemli detay: bir sorgudaki hint sadece o tabloyu etkiler. Aşağıdaki örnekte sadece t6 hint’in etkisinde, t5 hâlâ Optimized Locking’den faydalanıyor:

UPDATE t5
SET t5.b = t6.b
FROM t5
INNER JOIN t6 WITH (REPEATABLEREAD)
ON t5.a = t6.a;

Pratik öneri: tüm lock hint kullanımlarınızı gözden geçirin. Gerçekten gerekli olanları bırakın, performans için spekülatif eklenenleri çıkarın. Optimized Locking’ye geçişte en çok kazanan sorgular hint’siz olanlar. Hint envanterini çıkarmak için aşağıdaki sorgu işinize yarayabilir:

-- sql_modules üzerinde hint envanteri
SELECT
OBJECT_SCHEMA_NAME(object_id) AS schema_name,
OBJECT_NAME(object_id) AS object_name,
o.type_desc
FROM sys.sql_modules m
JOIN sys.objects o
ON m.object_id = o.object_id
WHERE m.definition LIKE '%UPDLOCK%'
OR m.definition LIKE '%HOLDLOCK%'
OR m.definition LIKE '%XLOCK%'
OR m.definition LIKE '%REPEATABLEREAD%'
OR m.definition LIKE '%READCOMMITTEDLOCK%';

Çıkan listede her satır gözden geçirilmesi gereken bir adim. UPDLOCK ile başlayıp sonradan UPDATE eden sıralı pattern’lerde hint genelde gerekli; salt okuma sorgularında spekülatif eklenmiş hint’leri silmek hem Optimized Locking faydasını hem genel concurrency’yi yukarı çekiyor.

12. Production Geçişi — Pratik Checklist

Optimized Locking’yi bir production database’e açmadan önce şu adımları sırayla geçmenizi öneririm. Bu liste, kaç ay süren rollout projelerinde dümeni çevirip duran detaylardan damıttığım bir versiyondur:

  • Test ortamında ADR aç → RCSI aç → OPTIMIZED_LOCKING aç sırasını uygula. RCSI kapalıysa kullanıcı bağlantılarının atılacağını unutma.
  • Lock hint envanterini çıkar (yukarıdaki sql_modules sorgusu). Spekülatif hint’leri ayrı bir backlog’a al.
  • OUTPUT clause + LAQ inceliği, uygulama kodunda OUTPUT clause kullanan UPDATE/MERGE’lerin listesini çıkar; bunlarda LAQ devre dışı, davranış değişmez ama beklentinizi netleştirin.
  • İş kuralı semantiğini sorgula, özellikle ‘state machine’ tarzı, kilit sırasına bağlı update zinciri var mı? Workshop 2’deki (1,2)/(1,3) farkı bu desende kritik. Gerekirse READCOMMITTEDLOCK hint’iyle kritik path’leri koru.
  • Production verisinin bir kopyasında baseline workload çalıştır, lock_after_qual_stmt_abort event’ini izle. Yüksek frekansta abort oluyorsa hangi sorgular tetikliyor incele.
  • Lock memory grafiklerini öncesi/sonrası kıyasla (sys.dm_os_memory_clerks → OBJECTSTORE_LOCK_MANAGER).
  • Deadlock telemetrisini izle, deadlock sayısı düşmeli ama format değişiyor; alarm/dashboard’larında <xactlock> tag’lerini bekleyecek şekilde güncelle.
  • Rollback planı: bir sorun olursa OL → kapat, RCSI → opsiyonel kapat, ADR → opsiyonel kapat. Pre-rollback’te aktif transaction’ları izle.

13. Bilmemiz Gereken Sınırlar

  • tempdb ve temporary table’lar: OL aktif değil. Geçici tablolar üzerindeki DML klasik kilitleme yapar.
  • Read-only secondary replica’lar: Çalışmaz, çünkü zaten DML çalışmıyor.
  • Schema lock’ları: ALTER TABLE, CREATE INDEX gibi DDL işlemlerinin schema lock’ları aynen devam ediyor. OL sadece DML (INSERT/UPDATE/DELETE/MERGE) lock’larını etkiler.
  • REPEATABLE READ ve SERIALIZABLE isolation: Bu seviyelerde lock’lar yine transaction sonuna kadar tutuluyor; TID’nin faydası kısıtlanır, SIL devre dışı.
  • LOB kolonlu satırlar: varchar(max), nvarchar(max), varbinary(max), json kolonları olan satırlarda SIL devre dışı; SIL faydası alamazsınız.
  • Page split olan sayfalar: Aynı transaction içinde split yaşamış sayfalardaki satırlar SIL kapsamı dışında.
  • OUTPUT clause + variable assignment UPDATE: LAQ baştan devre dışı.
  • Production’a açmadan önce performans testi şart: LAQ semantiği etkileyen sorguları, hint envanteri, lock metric’lerini öncesi/sonrası ölç.

14. Bitiriyoruz

Optimized Locking, SQL Server 2025’in iç dünyasında en köklü değişikliklerden biri ve sessiz sedasız geldi. Üç bileşen, TID, LAQ, SIL, birbirini tamamlayıp yıllardır alıştığımız ‘lock count = transaction satır sayısı + biraz daha’ formülünü emekliye ayırıyor.

Bu yazıdaki workshop’ları kendi orrtamınızda mutlaka çalıştırmanızı tavsiye ederim. Lock counts’u öncesi/sonrası kıyaslamak teknik tarafı somutlaştırır; LAQ’ın (1,2)/(1,3) semantik farkını kendi gözünüzle görmek de iş kuralı tarafında ne kadar dikkatli olunması gerektiğini anlatır.

Sonraki yazıda SQL Server 2025’in Native JSON Data Type’ı üzerine eğileceğiz. Storage tarafındaki etkisi, .modify() metodu, JSON_OBJECTAGG / JSON_ARRAYAGG gibi yeni agregation fonksiyonları ve yeni CREATE JSON INDEX söz dizimi, hepsini örneklerle göreceğiz. Bonus olarak: JSON kolonu olan satırlarda OL’nin SIL katmanının devre dışı kaldığı detayını da hatırlatacağım, çünkü iki konu kesişiyor.

Optimized Locking’yi kendi sisteminizde denerseniz lock sayılarını yorumlara yazabilirsiniz, özellikle tipik bir batch update senaryosunda öncesi/sonrası farkını paylaşırsanız ikinci bölümde örnek olarak yer veririm. lock_after_qual_stmt_abort event’inin sıklığı da merak ettiğim bir veri; canlı workload’larınızdaki sayıyı yorumlara düşerseniz toplu bir analiz yapabiliriz.


Yazar hakkında

Yavuz Filizlibay — Database Solution Architect

SQL Server ekosisteminde uzun yıllardır performans, güvenlik, yüksek erişilebilirlik üzerine çalışıyorum. SQL Server Administration, Querying, Performans ve Security eğitimleri ile danışmanlık hizmeti veriyorum. Yeni makalelerden haberdar olmak için LinkedIn’de bağlanabilir, eğitim veya danışmanlık için iletişime geçebilirsiniz.


Yavuz Filizlibay sitesinden daha fazla şey keşfedin

Subscribe to get the latest posts sent to your email.

,

Bir Cevap Yazın

Bu site istenmeyenleri azaltmak için Akismet kullanır. Yorum verilerinizin nasıl işlendiğini öğrenin.

Yavuz Filizlibay sitesinden daha fazla şey keşfedin

Okumaya devam etmek ve tüm arşive erişim kazanmak için hemen abone olun.

Okumaya Devam Edin

Yavuz Filizlibay sitesinden daha fazla şey keşfedin

Okumaya devam etmek ve tüm arşive erişim kazanmak için hemen abone olun.

Okumaya Devam Edin