7. Verilere eşzamanlı erişim yönetimi
Şimdiye kadar sadece bizim kullandığımız tablolar kullandık. Pratikte, çok kullanıcılı bir makinede veriler çoğunlukla farklı kullanıcılar arasında paylaşılır. Bu durumda şu soru ortaya çıkar: Hangi kullanıcı hangi tabloyu hangi şekilde (görüntüleme, ekleme, silme, değiştirme, ...) kullanabilir?
7.1. Firebird kullanıcılarının oluşturulması
IB-Expert ile çalışırken, SYSDBA kullanıcısı olarak oturum açtık. Bu bilgiyi, SGBD'e açık olan bağlantının özelliklerinde bulabiliriz:
![]() | ![]() |
Sağ tarafta, oturum açan kullanıcının [SYSDBA] olduğu görülüyor. Görünmeyen şey ise şifresi olan [masterkey]'tir. [SYSDBA], Firebird'ün özel bir kullanıcısıdır: SGBD tarafından yönetilen tüm nesneler üzerinde tam yetkiye sahiptir. IBExpert ile [Tools / User Manager] seçeneğini kullanarak veya aşağıdaki simgeyi kullanarak yeni kullanıcılar oluşturulabilir:

Kullanıcı yönetimi penceresi açılır:

[Add] düğmesi, yeni kullanıcılar oluşturmaya olanak tanır:

Şu kullanıcıları oluşturalım:
ad | şifre |
ADMIN1 | admin1 |
ADMIN2 | admin2 |
SELECT1 | select1 |
SELECT2 | select2 |
UPDATE1 | update1 |
UPDATE2 | update2 |
7.2. Kullanıcılara erişim hakları verme
Bir veritabanı, onu oluşturan kişiye aittir. Şimdiye kadar oluşturduğumuz veritabanları [SYSDBA] kullanıcısına aitti. Haklar kavramını açıklamak için, [ADMIN1, admin1] kimliği altında yeni bir veritabanı oluşturalım (Database / Create Database):

ve bunu DBACCES (ADMIN1) takma adıyla kaydedelim. Takma ad kullanımı, aynı veritabanına farklı kimlikler atayarak bağlantı açmaya olanak tanır; bu da IBExpert veritabanı gezgininde bu bağlantıları daha kolay tespit etmeyi sağlar:
![]() | ![]() |
Şimdi şu iki tabloyu oluşturalım: TA ve TB:
TA tablosu
![]() |
TB tablosu
![]() |
Bu tablolar arasında herhangi bir bağlantı yoktur.
IB-Expert ile, [DBACCES] veritabanına ikinci bir bağlantı oluşturalım; bu sefer [ADMIN2 / admin2] adıyla. Bunun için [Database / Register Database] seçeneğini kullanıyoruz:
![]() | ![]() |
DBACCES (ADMIN2) dosyasına gidelim ve SQL düzenleyicisini açalım (Shift + F12):
![]() |
Aynı [DBACCES] veritabanında çeşitli bağlantılar kullanma fırsatımız olacak. Her biri için bir SQL düzenleyicimiz olacak. [1]'te, SQL düzenleyicisi, bağlı veritabanının takma adını gösterir. Bu bilgiyi kullanarak hangi SQL düzenleyicisinde olduğunuzu öğrenebilirsiniz. Bu önemli olacaktır, çünkü veritabanındaki nesneler üzerinde aynı erişim haklarına sahip olmayan bağlantılar oluşturacağız.
TA tablosunun içeriğini sorgulayalım:

Aşağıdaki hata mesajını alıyoruz:

Bu ne anlama geliyor? [DBACCESS] veritabanı, [ADMIN1] kullanıcısı tarafından oluşturulmuştur ve dolayısıyla bu kullanıcıya aittir. Bu veritabanındaki çeşitli nesnelere yalnızca bu kullanıcı erişebilir. SQL GRANT komutuyla diğer kullanıcılara erişim hakları verebilir. Bu komutun çeşitli sözdizimleri vardır. Bunlardan biri şöyledir:
GRANT ayrıcalık1, ayrıcalık2, ...| ALL PRIVILEGES ON table/vue TO kullanıcı1, kullanıcı2, ...| PUBLIC [ WITH GRANT OPTION ] | |
privilègei erişim ayrıcalıklarını veya tüm ayrıcalıkları (ALL PRIVILEGES) table veya vue üzerinde utilisateuri kullanıcılarına veya tüm kullanıcılara ( PUBLIC ). WITH, GRANT ve OPTION maddeleri, bu ayrıcalıkları alan kullanıcıların bunları başka kullanıcılara devretmelerine olanak tanır. |
Verilebilecek privilègei ayrıcalıkları arasında şunlar bulunmaktadır:
tablo veya görünüm üzerinde DELETE komutunu kullanma hakkı. | |
tablo veya görünüm üzerinde INSERT komutunu kullanma hakkı | |
tablo veya görünüm üzerinde SELECT komutunu kullanma hakkı | |
tablo veya görünüm üzerinde UPDATE komutunu kullanma hakkı. Bu hak, şu sözdizimi kullanılarak belirli sütunlarla sınırlandırılabilir: GRANT güncelle ( col1, col2, ...) ON tablo/görünüm TO kullanıcı1, kullanıcı2, ...| PUBLIC [ WITH GRANT OPTION ] |
[ADMIN2] kullanıcıya SELECT hakkını TA tablosu üzerinde verelim. Bu izni yalnızca tablonun sahibi verebilir, c.a.d. Burada [ADMIN1]. DBACCES (ADMIN1) bağlantısına gidelim ve yeni bir düzenleyici açalım: SQL (Shift+F12):

Ardından, SQL düzenleyicisinden diğerine geçeceğiz. Karışıklığı önlemek için menüdeki [Windows] seçeneğini kullanabiliriz:

Yukarıda, her biri belirli bir kullanıcıyla ilişkili iki düzenleyici SQL görülüyor. SQL (ADMIN1) düzenleyicisine geri dönelim ve şu komutu verelim:

Ardından bunu bir COMMIT komutuyla onaylayalım:

Bunu yaptıktan sonra, ADMIN2 kullanıcı editörüne geçip, başarısız olan SELECT komutunu yeniden çalıştıralım:

Aşağıdaki hata mesajını alıyoruz:

[ADMIN2] kullanıcısı, [TA] tablosunu görüntüleme hakkına hâlâ sahip değil. Aslında, bir kullanıcının izinleri oturum açtığı anda yükleniyor gibi görünüyor. Bu durumda [ADMIN2], oturum açtığı andaki izinlere, yani hiçbir izne sahip olmaya devam eder. Bunu kontrol edelim. [ADMIN2] kullanıcısının oturumunu kapatalım:
- bağlantısına gidin
- bağlantıya sağ tıklayıp [Deconnect from database] seçeneğini seçerek veya (Shift + Ctrl + D) tuşlarına basarak oturumu kapatın

Bir pencere [COMMIT] bilgisini isterse, [COMMIT] değerini girin. Ardından, yukarıdaki [Reconnect] seçeneğini kullanarak [ADMIN2] kullanıcısını yeniden bağlayalım. Bu işlem tamamlandıktan sonra, SQL (ADMIN2) düzenleyicisine geri dönelim ve başarısız olan SELECT isteğini yeniden çalıştıralım:

Böylece şu sonucu elde ederiz:

Bu sefer ADMIN2, sahibi ADMIN1 tarafından kendisine verilen SELECT hakkı sayesinde TA tablosuna erişebilir. Normalde sahip olduğu tek izin budur. Bunu kontrol edelim. Hala SQL (ADMIN2) düzenleyicisinde:
![]() | ![]() |
Sağdaki ekran, ADMIN2'in TA tablosunda DELETE hakkına sahip olmadığını gösteriyor.
SQL (ADMIN1) düzenleyicisine geri dönüp ADMIN2 kullanıcısına daha fazla yetki verelim. Sırasıyla aşağıdaki iki komutu giriyoruz:
![]() | ![]() |
- İlk komut, ADMIN2 kullanıcısına [TA] tablosuna tüm erişim haklarını verir ve ayrıca bu kullanıcıya haklar verme yetkisi de tanır (WITH GRANT OPTION)
- ikinci komut, bir öncekini onaylar
Bu işlem tamamlandıktan sonra, daha önce yaptığımız gibi [ADMIN2] kullanıcısının bağlantısını yenileyelim (Bağlantıyı Kes / Yeniden Bağlan), ardından SQL (ADMIN2) düzenleyicisinde aşağıdaki komutları girelim:
![]() | ![]() | ![]() |
ADMIN2 komutu, TA tablosundaki tüm satırları silmiştir. ROLLBACK komutuyla bu silme işlemini geri alalım:
![]() | ![]() | ![]() |
ADMIN2 komutunun da TA tablosu üzerinde haklar verebildiğini kontrol edelim.
![]() | ![]() |
Şimdi, daha önce oluşturulan kullanıcılardan biri olan [SELECT1 / select1] adıyla [DBACCES] veritabanına (Veritabanı / Veritabanını kaydet) bir bağlantı açalım ve ardından [Database Explorer]'te oluşturulan bağlantıya çift tıklayalım:
![]() | ![]() |
Bu yeni bağlantıya geçelim ve yeni bir SQL düzenleyicisi açalım (Shift + F12), ardından aşağıdaki komutları girelim:
![]() | ![]() |
SELECT1 kullanıcısı, SELECT tablosunda TA hakkına sahiptir. Bu hakkı SELECT2 kullanıcısına devredebilir mi?
![]() |
İşlem, SELECT1 kullanıcısının, ADMIN2 kullanıcısından aldığı SELECT hakkını devretme yetkisini almamış olması nedeniyle başarısız oldu. Bunun içinADMIN2 kullanıcısının, SQL GRANT'teki siparişinde WITH, GRANT ve OPTION maddelerini kullanmaktadır. Aktarım kuralları basittir:
- bir kullanıcı yalnızca aldığı hakları iletebilir, daha fazlasını değil
- bu hakları ancak [WITH GRANT OPTION] ayrıcalığıyla almışsa aktarabilir
Verilen bir hak, REVOKE komutuyla geri alınabilir:
REVOKE ayrıcalık1, ayrıcalık2, ...| ALL PRIVILEGES ON table/vue FROM kullanıcı1, kullanıcı2, ...| PUBLIC | |
privilègei erişim ayrıcalıklarını veya tüm ayrıcalıkları (ALL PRIVILEGES) table veya vue üzerindeki erişim ayrıcalıklarını utilisateuri kullanıcılarından veya tüm kullanıcılardan ( PUBLIC ). |
Hadi deneyelim. ADMIN2'in SQL düzenleyicisine geri dönelim ve SELECT1 kullanıcısına verdiğimiz SELECT hakkını kaldıralım:
![]() | ![]() |
SELECT1 kullanıcısının bağlantısını kesip yeniden bağlayalım. Ardından SQL (SELECT1) düzenleyicisinde TA tablosunun içeriğini sorgulayalım:
![]() | ![]() |
SELECT1 kullanıcısı, TA tablosuna ilişkin okuma hakkını gerçekten kaybetmiştir. Bu hakkın kendisine ADMIN2 tarafından verildiği ve ADMIN2 tarafından kaldırıldığı unutulmamalıdır. ADMIN1 bu hakkı geri almaya çalışırsa herhangi bir hata bildirilmez, ancak daha sonra SELECT1'in SELECT hakkını koruduğu görülebilir.
Bir hak, şu sözdizimi kullanılarak herkese verilebilir: GRANT hak(lar) ON tablo / görünüm TO PUBLIC. Örneğin, TA tablosu üzerindeki SELECT hakkını herkese verelim. Bunu yapmak için ADMIN1 veya ADMIN2 kullanılabilir. ADMIN2'i kullanıyoruz:
![]() | ![]() |
USER1 / user1 kullanıcısıyla veritabanına bir bağlantı oluşturalım:
![]() | ![]() |
DBACCES (USER1) bağlantısıyla yeni bir SQL düzenleyicisi açalım (Shift + F12) ve aşağıdaki komutları girelim:
![]() | ![]() |
USER1 kullanıcısı, TA tablosunda SELECT hakkına sahiptir.
7.3. İşlemler
7.3.1. Sızdırmazlık Düzeyleri
Şimdi, veritabanındaki nesnelere erişim hakları konusunu bir kenara bırakıp, bu nesnelere eşzamanlı erişim konusunu ele alalım. Veritabanındaki bir nesneye (örneğin bir tabloya) yeterli erişim haklarına sahip iki kullanıcı, bu nesneyi aynı anda kullanmak istiyor. Ne olur?
Her kullanıcı bir işlem içinde çalışır. Bir işlem, "atomik" bir şekilde yürütülen SQL komut dizisidir:
- ya tüm işlemler başarılı olur
- ya da bunlardan biri başarısız olursa, ondan önceki tüm işlemler iptal edilir
Sonuç olarak, bir işlemin içindeki işlemler ya tümüyle başarıyla uygulanır ya da hiçbiri uygulanmaz. Kullanıcı işlemin kontrolünü elinde tuttuğunda (bu belgenin tamamında olduğu gibi), bir COMMIT komutuyla işlemi onaylar veya bir ROLLBACK komutuyla iptal eder.
Her kullanıcı kendisine ait bir işlem içinde çalışır. Farklı kullanıcılar arasında genellikle dört farklı yalıtım düzeyi ayırt edilir:
- Uncommitted Read
- Onaylanmış Okuma
- Tekrarlanabilir Okuma
- Serileştirilebilir
Onaylanmamış Okuma
Bu yalıtım modu "Dirty Read" olarak da adlandırılır. İşte bu modda neler olabileceğine dair bir örnek:
- U1 adlı bir kullanıcı, T tablosu üzerinde bir işlem başlatır
- U2 adlı bir kullanıcı aynı T tablosu üzerinde bir işlem başlatır
- U1 adlı kullanıcı, T tablosundaki satırları değiştirir ancak henüz onaylamaz
- U2 kullanıcısı bu değişiklikleri "görür" ve gördüklerine dayanarak kararlar alır
- kullanıcı, ROLLBACK ile işlemini iptal eder
- adımda, U2 kullanıcısının, daha sonra yanlış olduğu ortaya çıkacak verilere dayanarak bir karar verdiği görülmektedir.
Committed Read
Bu izolasyon modu, önceki sorunu önler. Bu modda, 4. adımdaki U2 kullanıcısı, U1 kullanıcısının T tablosunda yaptığı değişiklikleri "görmeyecektir". Bu değişiklikleri ancak U1 kullanıcısı işlemini tamamladıktan sonra görebilir.
"Unrepeatable Read" olarak da adlandırılan bu modda, aşağıdaki durumlarla karşılaşılabilir:
- U1 adlı bir kullanıcı, T tablosu üzerinde bir işlem başlatır
- U2 adlı bir kullanıcı aynı T tablosunda bir işlem başlatır
- U2 kullanıcısı, belirli bir koşulu karşılayan T tablosundaki satırların C sütunundaki ortalamayı hesaplamak için bir SELECT işlemi gerçekleştirir
- U1 kullanıcısı, T tablosunun C sütunundaki bazı değerleri değiştirir (UPDATE) ve bunları onaylar (COMMIT)
- U2 kullanıcısı, 3. adımdaki ile aynı SELECT işlemini tekrar gerçekleştirir. U1 tarafından yapılan değişiklikler nedeniyle C sütununun ortalamasının değiştiğini fark edecektir.
Şimdi U2 kullanıcısı, yalnızca U1 tarafından "onaylanan" değişiklikleri görebilir. Ancak aynı işlem içinde kalırken, 3 ve 5 numaralı iki özdeş işlem farklı sonuçlar verir. "Unrepeatable Read" terimi bu durumu ifade eder. Bu, T tablosunun sabit bir görüntüsüne sahip olmak isteyen biri için can sıkıcı bir durumdur.
Tekrarlanabilir Okuma
Bu izolasyon modunda, bir kullanıcı aynı işlem içinde kaldığı sürece veritabanından yaptığı okumalarda aynı sonuçları alacağı garanti edilir. Kullanıcı, diğer işlemler tarafından yapılan değişikliklerin (onaylanmış olsalar bile) asla yansıtılmadığı bir anlık görüntü üzerinde çalışır. Bu değişiklikleri ancak kendisi COMMIT veya ROLLBACK komutuyla işlemini tamamladığında görebilir.
Ancak bu izolasyon modu henüz mükemmel değildir. Yukarıdaki 3. işlemden sonra, U2 kullanıcısı tarafından sorgulanan satırlar kilitlenir. 4. işlem sırasında, U1 kullanıcısı bu satırların C sütunundaki değerleri (UPDATE) değiştiremez. Ancak yeni satırlar ekleyebilir (INSERT). Eklenen satırlardan bazıları 3. adımda test edilen koşulu karşılıyorsa, 5. işlemde eklenen satırlar nedeniyle 3. adımda bulunan ortalamadan farklı bir ortalama elde edilecektir.
Bu yeni sorunu çözmek için "Serializable" izolasyon moduna geçmek gerekir.
Serializable
Bu izolasyon modunda, işlemler birbirinden tamamen yalıtılmıştır. Bu mod, eşzamanlı olarak yürütülen iki işlemin sonucunun, sırayla gerçekleştirilmiş olsaydı elde edilecek sonuçla aynı olmasını garanti eder. Bu sonuca ulaşmak için, U1 kullanıcısının, U1 kullanıcısının SELECT işleminin sonucunu değiştirecek satırlar eklemek istediği 4. işlem sırasında, bu işlem engellenecektir. Bir hata mesajı, eklemenin mümkün olmadığını bildirecektir. U2 kullanıcısı işlemini onayladığında ekleme mümkün hale gelecektir.
Dört işlem yalıtım seviyesi SQL, tüm SGBD'lerde mevcut değildir. Firebird aşağıdaki yalıtım seviyelerini sunar:
- snapshot: varsayılan yalıtım modu. SQL standardındaki "Repeatable Read" moduna karşılık gelir.
- committed read: SQL standardındaki "committed read" moduna karşılık gelir
Bu yalıtım düzeyi, SET TRANSACTION komutuyla belirlenir:
SET TRANSACTION [READ WRITE | READ ONLY] [WAIT|NOWAIT] ISOLATION LEVEL [SNAPSHOT | READ COMMITTED] | |
altı çizili anahtar kelimeler varsayılan değerlerdir READ WRITE: işlem okuma ve yazma yetkisine sahiptir READ ONLY: İşlem yalnızca okuma yapabilir WAIT: İki işlem arasında çakışma olması durumunda, işlemini gerçekleştiremeyen işlem, diğer işlemin onaylanmasını bekler. Artık SQL emirleri veremez. NOWAIT: İşlemini gerçekleştiremeyen işlem engellenmez. Bir hata mesajı alır ve çalışmaya devam edebilir. ISOLATION LEVEL [SNAPSHOT | READ COMMITTED]: yalıtım düzeyi |
Deneyelim. SQL (ADMIN1) düzenleyicisinde şu SQL komutunu girin:

Gördüğümüz gibi bu komut kabul edilmedi. Nedenini bilmiyoruz...
IB-Expert, izolasyon modunu başka bir şekilde ayarlamaya olanak tanır. DBACCES(ADMIN1) bağlantısına sağ tıklayıp [Database Registration Info] seçeneğini seçelim:
![]() | ![]() |
Sağdaki ekran, [Transactions] seçeneğinin mevcut olduğunu göstermektedir. Bu seçenek, işlemlerin yalıtım düzeyini belirlememizi sağlayacaktır. Burada bunu [snapshot] olarak ayarlıyoruz. Aynı işlemi DBACCES (ADMIN2) bağlantısı için de yapıyoruz.
7.3.2. Anlık görüntü modu
Firebird'ün varsayılan yalıtım modu olan snapshot yalıtım seviyesini inceleyelim. Kullanıcı bir işlem başlattığında, veritabanının bir anlık görüntüsü alınır. Kullanıcı daha sonra bu anlık görüntü üzerinde çalışır. Böylece her kullanıcı kendisine ait veritabanı anlık görüntüsü üzerinde çalışır. Kullanıcı bu görüntüde değişiklik yaparsa, diğer kullanıcılar bu değişiklikleri göremez. Değişiklikleri, değişiklikleri yapan kullanıcı bir COMMIT ile onayladıktan sonra görebilirler.
İki durum düşünülebilir:
- bir kullanıcı tabloyu okurken (select), başka bir kullanıcı tabloyu değiştiriyorsa (insert, update, delete)
- iki kullanıcı da tabloyu aynı anda değiştirmek istiyor
7.3.2.1. Tutarlı okuma ilkesi
Aynı TAB tablosu üzerinde çalışan U1 ve U2 adlı iki kullanıcı olduğunu varsayalım:
U1 kullanıcısının işlemi, T1a zamanında başlar ve T1b zamanında biter.
U2 kullanıcısının işlemi, T2a zamanında başlar ve T2b zamanında sona erer.
U1, T1a zamanında çekilmiş olan TAB’in fotoğrafı üzerinde çalışıyor. T1a ile T1b arasında, TAB'i düzenliyor. Diğer kullanıcılar bu değişikliklere ancak T1b zamanında, U1'in bir COMMIT oluşturduğu zaman erişebilecekler.
U2, TAB'in T2a zamanında çektiği bir fotoğraf üzerinde çalışır; yani U1 tarafından kullanılan fotoğrafın aynısıdır (bu arada diğer kullanıcılar orijinali değiştirmediyse). U1 kullanıcısının TAB üzerinde yaptığı değişiklikleri "göremiyor". Bu değişiklikleri ancak T1b zamanında görebilecek.
Bu durumu [DBACCES] veritabanımız üzerinde örnekleyelim. [ADMIN1] ve [ADMIN2] adlı iki kullanıcının aynı anda çalışmasını sağlayacağız. DBACCES (ADMIN1) bağlantısına geçelim ve ADMIN1'in SQL düzenleyicisinde aşağıdaki işlemleri yapalım:
![]() | ![]() | ![]() |
ADMIN1, TA tablosunun 2 numaralı satırını değiştirdi ancak işlemini henüz onaylamadı (COMMIT). Kullanıcı ADMIN2 daha sonra TA tablosunda bir SELECT işlemi gerçekleştirir (ADMIN2'ten SQL düzenleyicisine geçilir). Örnekteki T2a zamanından önceyiz.
![]() | ![]() |
ADMIN1'ten SQL düzenleyicisine geri dönüyoruz; bu düzenleyici ekleneni onaylıyor:
![]() |
ADMIN2 dosyasının düzenleyicisi SQL'e geri dönerek SELECT dosyasını yeniden oluşturmak:
![]() | ![]() |
ADMIN2, ADMIN1 tarafından yapılan değişiklikleri görür. Anlık görüntü modunda, bir işlem, diğer işlemler tamamlanana kadar bu işlemler tarafından yapılan değişiklikleri göremez.
7.3.2.2. Aynı veritabanı nesnesinin iki işlem tarafından eşzamanlı olarak değiştirilmesi
Muhasebe alanından bir örnek verelim: U1 ve U2 hesaplar üzerinde çalışmaktadır. U1, comptex'ten S tutarında bir meblağı borç kaydeder ve aynı tutarı comptey'e alacak olarak kaydeder. Bunu birkaç adımda gerçekleştirecektir:
U1, T1a zamanında bir işlem başlatır, T1b zamanında comptex hesabından para çeker, T1c zamanında comptey hesabına para yatırır ve T1d zamanında her iki işlemi de onaylar. Ayrıca, U2'in de aynı şeyi yapmak istediğini varsayalım; bu hesap, aşağıdaki şemaya göre işlemi T2a zamanında başlatır ve T2d zamanında sonlandırır:
--------+----------+----+----+-------+------+-----+-------+---------
T1a T1b T2a T1c T2b T1d T2c T2d
T2 zamanında, U2 için hesap tablosunun bir anlık görüntüsü alınır. Bu görüntü, snapshot ilkesine göre tutarlıdır. U2, comptex ve comptey hesaplarının başlangıç durumunu görür, çünkü U1 henüz işlemlerini onaylamamıştır.
comptex'in başlangıç bakiyesinin 1000 € olduğunu ve U1 ile U2 kullanıcılarının her birinin bu hesaptan 100 € çekmek istediğini varsayalım.
- T1b zamanında, U1, comptex'in bakiyesinden 100 € düşürür ve böylece bakiyesini 90 €'ya indirir. Bu işlem ancak T1d zamanında onaylanacaktır.
- T2b zamanında, U2, comptex'in bakiyesini 1000 € olarak görür (tutarlı okuma ilkesi) ve bu tutarı 100 € azaltarak 90 €'ya düşürür.
- Sonuç olarak, her şeyin onaylandığı T2d zamanında, comptex'in bakiyesi beklenen 80 € yerine 90 € olacaktır.
Bu sorunun çözümü, U1'in işlemini tamamlamadığı sürece U2'in comptex'i değiştirmesini engellemektir. Böylece U2, T1d zamanına kadar bloke edilecektir. snapshot modu bu mekanizmayı sağlar.
Bunu DBACCES veritabanı ile örneklendirelim. ADMIN1, SQL (ADMIN1) düzenleyicisinde bir işlem başlatır:
![]() | ![]() | ![]() | ![]() |
Yeni bir işlem başlattığımızdan emin olmak için önce bir COMMIT oluşturduk. Ardından 4 numaralı satırı sildik. İşlem henüz onaylanmadı.
ADMIN2 ise kendi düzenleyicisi SQL (ADMIN2) içinde bir işlem başlatıyor:
![]() | ![]() |
Sağdaki ekran, ADMIN2'in 4 numaralı satırı değiştirmek istediğini göstermektedir. Başka bir kullanıcı bu satırı daha önce değiştirmiş ancak değişikliği henüz onaylamamış olduğu için bunun mümkün olmadığı yanıtı verilmiştir.
SQL (ADMIN1) düzenleyicisine geri dönüp COMMIT'i oluşturalım:

SQL (ADMIN2) düzenleyicisine geri dönüp UPDATE komutunu tekrar çalıştıralım:
![]() | ![]() |
![]() | ![]() |
UPDATE işlemi, aşağıdaki SELECT'te de görüldüğü gibi 4 numaralı satır artık mevcut olmamasına rağmen sorunsuz bir şekilde gerçekleşir. İşte bu anda ADMIN2, söz konusu satırın artık mevcut olmadığını fark eder.
7.3.2.3. Tekrarlanabilir Okuma Modu
Şimdi "Repeatable Read" modunu örneklerle açıklayalım. Bu izolasyon seviyesi, "snapshot" modu tarafından sağlanır. Bu mod, bir işlemin veritabanını okurken her zaman aynı sonucu almasını garanti eder.
Öncelikle, ADMIN2'in düzenleyicisi olan SQL ile çalışmaya başlayalım:
![]() | ![]() | ![]() |
![]() | ![]() |
Şimdi SQL düzenleyicisine geçelim:
![]() | ![]() | ![]() |
![]() | ![]() | ![]() |
![]() | ![]() |
ADMIN1 kullanıcısı iki satır ekledi ve işlemini onayladı. Şimdi SQL (ADMIN2) düzenleyicisine geri dönüp SELECT SUM işlemlerini tekrar yapalım:
![]() | ![]() |
Görüldüğü üzere, ADMIN2, ADMIN1'teki satır eklemelerini görmüyor; oysa bu eklemeler bir COMMIT tarafından onaylanmıştı. SELECT SUM, eklemelerden önceki ile aynı sonucu veriyor. Bu, Repeatable Read ilkesidir.
Şimdi, yine SQL (ADMIN2) içinde, işlemi bir COMMIT ile onaylayalım ve ardından SELECT SUM komutlarını tekrar çalıştıralım:
![]() | ![]() | ![]() |
ADMIN1 tarafından eklenen satırlar artık dikkate alınmaktadır.
7.3.3. Committed Read modu
Şimdi "Committed Read" modunu inceleyelim. Bu yalıtım düzeyi, "Repeatable Read" hariç olmak üzere snapshot'inkine benzerdir.
Öncelikle, her iki bağlantının işlem yalıtım düzeyini değiştiriyoruz.
- ADMIN1 ve ADMIN2 kullanıcılarının bağlantısını kesiyoruz
- İşlemlerinin yalıtım düzeyini değiştiriyoruz

- ADMIN1 ve ADMIN2 kullanıcılarını yeniden bağlayalım
Şimdi, "Repeatable Read"i gösteren önceki örneği tekrar ele alalım ve artık aynı davranışın görülmediğini gösterelim. Öncelikle, ADMIN2'in düzenleyicisi olan SQL ile çalışmaya başlayalım:
![]() | ![]() | ![]() |
![]() | ![]() |
Şimdi SQL düzenleyicisine geçelim:
![]() | ![]() | ![]() |
![]() | ![]() | ![]() |
![]() | ![]() |
ADMIN1 kullanıcısı iki satır ekledi ve işlemini onayladı. Şimdi SQL (ADMIN2) düzenleyicisine geri dönüp SELECT SUM işlemlerini tekrar yapalım:
![]() | ![]() |
SELECT ve SUM, ADMIN1 tarafından yapılan eklemelerden önceki sonuçlarla aynı sonucu vermiyor. Bu, snapshot ve read committed modları arasındaki farktır.








































































