SQL Server Transaction ve With Nolock
Sql server üzerinde kullanıcı tablo ‘da bir kaydı açıp üzerinde işlem yapıyorsa o kayıt SQL Server Veritabanı motoru tarafından “Locking” kilitlenir ve kullanıcı işlemini bitirene kadar başkası tarafından işlem yapılmasına izin vermez. Böylece aynı kayıt üzerinde işlem yapmak isteyen kullanıcı diğer kullanıcının işleminin bitmesini beklemek zorundadır. Küçük ölçekli işletmeler tarafından kullanılan Veritabanlarında bu işlem pek hissedilmese de, aynı anda milyonlarca işlemin yapıldığı büyük ölçekli projelerde ciddi şekilde hissedilmektedir.
Peki, bu durumun önüne geçmek için ne yapılabilir?
SQL Sorgu cümleciğimizde WITH (NOLOCK) deyimini kullanacağız.
Basitçe sorgumuzun dizilimi
select * from Customers WITH (NOLOCK)
Şeklinde kullanarak “Customers” tablosunda kilit oluşturmadan başka kullanıcılar tarafından da kayıt girilmesini, güncellemesini ve silmesini sağlayabiliriz. Bu yöntem avantaj sağlayabileceği gibi ciddi dezavantajlarda ortaya çıkartabilir. Örnek olarak bir tablo üzerinde Son 1 adet kalan ürüne aynı anda 2 kişi birden işlem yaptılar. Tablo kilitli olmadığı için ürün aynı anda işlem yapan 2 kişiye birden hata vermeden aktarıldı. Tabi ki örneğimizi 2 kişi olarak verdik.Bu sayı çok daha fazla olabilir, bunun sonucunda ise ciddi karmaşıklıklar çıkabilir.Bu karmaşıklığı önlemek içinse “TRANSACTION” kullanmamız gerekir.
Transaction kullanımında işlemler sırasıyla gerçekleştirilmelidir.
- Sistemde istenilen ürün adedi kadar ürün kontrol edilir
- Ürün varsa Transaction başlatılır
- Mevcut üründen istenilen ürün adedi kadar düşülür
- Transaction tamamlanır
- Ürün yoksa İsteği reddet
Şimdi bunu SQL kodu olarak nasıl yapacağız bunu inceleyelim.
create procedure TRANSACTION
@UrunIstekAdet int,
@ProductID int
AS
BEGIN
Declare @MevcutUrun int
Declare @Result int
SET @MevcutUrun = (select UnitsInStock from Products Where ProductID=@ProductID)
if @UrunIstekAdet <= @MevcutUrun
BEGIN
BEGIN TRANSACTION
Update Products SET UnitsInStock =UnitsInStock – @UrunIstekAdet Where ProductID = @ProductID
IF @@ERROR=0
BEGIN
COMMIT TRANSACTION
SET @Result=0
end else
BEGIN
ROLLBACK TRANSACTION
SET @Result = 1
end
end else
BEGIN
SET @result=2
END
RETURN @result
end
Yukarıdaki işlemleri sırasıyla inceleyelim.
@MevcutUrun = Elimizde bulunan ürün sayısını alıyoruz.
SET @MevcutUrun = (select UnitsInStock from Products Where ProductID=@ProductID)
Kullanıcının seçtiği ürün ile “@MevcutUrun” eşleştriyoruz.
if @UrunIstekAdet <= @MevcutUrun
MevcutUrunulunan ürün sayısını alıyoruz.
Eğer kullanıcın seçtiği ürün “@MevcutUrun” Sayısından düşük yada eşitse işlem devam edecek aksi halde dönen “@Result” değeri 2 olacaktır.
BEGIN TRANSACTION
Update Products SET UnitsInStock =UnitsInStock – @UrunIstekAdet Where ProductID = @ProductID
Transaction başlattık ve seçilen üründen istenilen ürün adedi kadar düştük. “@Result” değeri 0 olacaktır.
COMMIT TRANSACTION
SET @Result=0
Peki aynı anda ürünü isteyen olsaydı ne olacaktır.
ROLLBACK TRANSACTION
SET @Result = 1
Transaction yapılan işlemi geri alacak ve kullanıcıya ürün kalmadığını bildircektir. “@Result” değeri 1TRANSEı önlemek içinse “TRANSEalacak ve kullanıcıya ürün kalmadığını bildircekti.a olacaktır.
Böylece projelerimizin daha sağlıklı çalışmasını sağlayabiliriz. SQL TRANSACTION kullanımını basitçe bir örnekle anlatmaya çalıştım.
NOT=Projede Örnek veritabanı Northwind kullanılmıştır.