SQL Server’da Update (U) Lock, veri ambarı veya veritabanı yönetiminde “çakışmaları önlemek için kullanılan stratejik bir köprü” olarak tanımlanabilir. Genellikle bir UPDATE işlemi sırasında, sistem veriyi önce okuyup sonra değiştireceği için ortaya çıkar.
Normalde bir veriyi okurken Shared (S) kilit, değiştirirken Exclusive (X) kilit kullanılır. Ancak bir işlem önce veriyi okuyup (S), sonra güncellemeye (X) karar verirse; aynı anda başka bir işlem de aynısını yapmaya çalışırsa iki işlem de birbirinin S kilidini bırakmasını bekler. Bu durum Deadlock (Ölü Döngü) ile sonuçlanır.
Update (U) Lock, bu çıkmazı engellemek için araya girer.
Temel Özellikleri
- Okumaya İzin Verir: Bir satırda U kilidi varken diğer kullanıcılar o satırı okuyabilir (S lock alabilir).
- Yazmaya İzin Vermez: Bir satırda U kilidi varken başka hiçbir işlem o satırı değiştiremez veya başka bir U/X kilidi koyamaz.
- Dönüşüm: SQL Server veriyi güncelleyeceği kesinleştiği an U kilidini otomatik olarak Exclusive (X) kilide yükseltir.
Önce Shared Lock alır, sonra gerekirse Exclusive Lock’a çevirir. Update Lock (U), okuma ve yazma işlemlerine engel olacak şekilde işlev görür, ancak başka bir işlem bu satır üzerinde Shared Lock (S) alarak okuma yapabilir. Update Lock (U), SQL Server’ın bir satır üzerinde yazma işlemi yapmadan önce, o satırı “güncellenmeye hazırlanmak” amacıyla kilitlemesidir. Bu kilit türü, genellikle row-level kilidi olarak kullanılır ve Shared Lock (S)’in aksine, U kilidi satıra yalnızca yazma işlemi yapılacağı zaman alınır. Bu kilit, bir satırın güncellenmesine niyetlendiğini belirtir ve satır üzerinde yazma işlemi yapılacağı zaman başka bir işlem yazmaya müdahale edemez, ancak okuyabilir. Kısacası başlangıç adımı olarak U kilidinde select sorguları sıkıntı yaşamaz. Ne zaman U kilidi X kilidine dönüşürse sadece bu satır için bekleme yaşanmaktadır. SQL Server *lock escalation* denen bir mekanizmayla çok sayıda satır seviyesi kilidi sayfa veya tablo seviyesine yükseltebilir.
Aşağıdaki tablo, bir kaynak üzerinde U kilidi varken diğer kilitlerin durumunu gösterir:
| Mevcut Kilit | İstenecek Kilit | Sonuç | Açıklama |
| Update (U) | Shared (S) | Başarılı | Diğerleri veriyi okuyabilir. |
| Update (U) | Update (U) | Başarısız | Aynı anda iki işlem güncelleme niyetine giremez. |
| Update (U) | Exclusive (X) | Başarısız | U kilidi varken kimse veriyi yazamaz. |
Bir UPDATE sorgusu çalıştırdığınızda SQL Server şu adımları izler:
- Arama Aşaması: Güncellenecek satırı bulmak için tabloyu tarar. Bu sırada satırlara U kilidi koyar.
- Karar: Eğer satır kriterlere uymuyorsa U kilidini kaldırır.
- Güncelleme: Eğer satır güncellenecekse, U kilidini X kilidine çevirir ve veriyi değiştirir.
Özetle
Update (U) Lock, “Ben bu satırı okuyorum ve muhtemelen birazdan güncelleyeceğim, o yüzden benden başka kimse güncellemeye niyetlenmesin ama okumak isteyenler buyursun,” demektir.
Aşağıdaki komut ile update işlemi başlatılır.


Başka bir kullanıcı ilgili tabloya select çektiğinde sonuç dönmez. Ama tablomuz büyükse sql server ilgili id değerini bulmak için arama yaptığında okuma için izin vermektedir.


Lock konulan satır dışında başka bir satıra select çekildiğinde sonucumuz döner.

İlgili satıra başka bir kullanıcı lock koyduğunda ilgili lock yeni gelen kullanıcıda Exclusive lock’a dönüşür.


Lock Satır bazında olduğu için başka satırların update işlemi sıkıntısız gerçekleştirilir.

Tablo bazlı bir lock olmadığı için insert işleminde herhangi bir sıkıntıya sebebiyet vermez.

İlgili satıra herhangi bir delete işlemine izin vermez.

Yukarıda dikkat edersek tablomuzun üzerinde Update lock varken select işlemi farklı bir satır üzerinden gerçekleşmişti. Exclusive lock oluştuğunda aynı komut üzerinde select komutu çalıştırdığımızda locklar birbirleriyle uyumsuz olduğu için select işlemi gerçekleşmez.


UPDATE Customers SET Age = Age + 1 WHERE ID = 2;
Önce Update Lock (U) alır, eğer başka kimse kullanmıyorsa Exclusive Lock’a çevirir.
Deadlock Senaryosu (Update Lock Kullanımı)
BEGIN TRAN
UPDATE [Person].[Person] SET FirstName = 'Gigi' WHERE BusinessEntityID = 1; -- Update Lock (U)
WAITFOR DELAY '00:00:10' -- 10 saniye beklet
UPDATE [Sales].[SalesOrderDetail] SET OrderQty = 500 WHERE SalesOrderID = 1; -- Exclusive Lock (X)
COMMIT;
BEGIN TRAN
UPDATE [Sales].[SalesOrderDetail] SET OrderQty = 600 WHERE SalesOrderID = 1; -- Update Lock (U)
WAITFOR DELAY '00:00:10'
UPDATE [Person].[Person] SET FirstName = 'John' WHERE BusinessEntityID = 1; -- Exclusive Lock (X)
COMMIT;
Yukarıdaki iki komut deadlock oluşturabilmesi için ayrı sessionlarda aynı anda çalışması gerekmektedir. Deadlock oluşur çünkü her iki işlem birbirini bekliyor. Yukarıdaki kodda belirtilen sırasıyla update lock ve exclusive durumlarına değinelim.
İlk UPDATE komutunda Update Lock (U) kullanılır çünkü SQL Server, işlem başlamadan önce yalnızca satırda bir değişiklik yapılacağına dair bir hazırlık yapmaktadır. Bu U kilidi, SQL Server’ın güncelleme yapma niyetini gösterir. U kilidi, satırın sadece güncellenmeye uygun olup olmadığını kontrol etmek içindir. Yani, bir işlem U kilidi aldıktan sonra, başka bir işlem bu satırı okuyabilir ancak yazamaz. Daha sonra, işlem X kilidi almak için ilerler.
Transaction 1’de İkinci UPDATE komutunda Exclusive Lock (X) alınır yukarıda resimdede görmüş olduk çünkü, satırdaki veri gerçekten güncelleniyor ve tam erişim gereklidir. Exclusive Lock (X), bu satır üzerinde yapılan güncellemeyi başka hiçbir işlemle paylaşmanıza izin vermez. X kilidi, güncellemeyi tam anlamıyla tamamlamak ve veri üzerinde tam bir kontrol sağlamak için gereklidir.
U kilidi başlangıç aşaması için, X kilidi ise işlem tamamlanana kadar tam kontrol sağlamak için gereklidir.
Transaction 1, SalesOrderDetail tablosunda Exclusive Lock (X) almak ister, ancak Transaction 2 bu satırı Update Lock (U) ile kilitlemiştir. Dolayısıyla Transaction 1 T2’nin kilidini bekler.
Transaction 2 ise Person tablosunda Exclusive Lock (X) almak ister, ancak Transaction 1 bu satırı Update Lock (U) ile kilitlemiştir. Bu nedenle Transaction 2 de T1’in kilidini bekler.
Transaction 1’in ilk UPDATE komutu (Person tablosunda) ile Transaction 2’nin ikinci UPDATE komutu (Person tablosunda) arasında doğrudan bir bağlantı vardır, çünkü her iki işlem de Person tablosundaki aynı kaynağı kilitlemeye çalışır.
Aynı şekilde, Transaction 1’in ikinci UPDATE komutu (SalesOrderDetail tablosunda) ile Transaction 2’nin ilk UPDATE komutu (SalesOrderDetail tablosunda) arasında da bir bağlantı vardır, çünkü her iki işlem de SalesOrderDetail tablosundaki aynı kaynağı kilitlemeye çalışır.
Deadlock oluşmaması için yapılacak olan adım Transactions’ları kısa tutulması gerekmektedir. Update işlemlerini hep aynı satırda yapılması gerekmektedir. NOLOCK veya READ COMMITTED kullanarak kilitleri optimize etmek gerekmektedir.
Bu kilit geçici bir önkilit (pre-emptive lock) olarak kullanılır. Yani, SQL Server verinin gerçekten güncellenip güncellenmeyeceğini görmek için bu kilidi alır.
Eğer veride gerçekten bir değişiklik yapılacaksa, bu durumda Update Lock Exclusive Lock’a dönüşür.
Update Lock kullanmak, SQL Server’ın gereksiz yere güçlü kilitler koymaktan kaçınmasını sağlar ve kilit çakışmalarını azaltır.
Başka makalede görüşmek dileğiyle..
*Göklerde ve yerde ne varsa hepsi Allah’ındır. Allah’ın ilmi ve kudreti her şeyi kuşatmıştır. Nisa-126*
