MVCC
MVCC Tanıtımı
MVCC
MVCC, yani Çok Sürümlü Eşzamanlılık Denetimi, veritabanlarında aynı anda birden fazla işlemin (transaction) çakışmadan ve kilitlenmeden çalışmasını sağlayan bir yöntemdir. Veriye ait birden fazla sürüm (version) oluşturarak okuma ve yazma işlemlerinin birbirini engellemesini önler.
2 Farklı oturum açıp bir senaryo ile bu yapıyı test edelim;
Session A
\set AUTOCOMMIT OFF
select txid_current();
insert into ogretmenler values (3,'Emre’);
update ogretmenler set isim =’erol’ where id=2;
select xmin, xmax, id, isim from ogretmenler ;
select txid_current();
Session B
Session B üzerinden bu tabloyu ve txid mizi sorgulayalım;
select xmin, xmax, id, name,surname from mvcc_test ; Session B üzerinden sorguladığımızda session A da yapılan hiçbir değişikliği görmüyoruz, yani MVCC ye göre eski versiyonları görüyoruz, çünkü Session A da transaction henüz commit olmadı. Değişiklikler Commit olmadı ancak halen select sorgularımız çalışıyor herhangi bir Lock da yaşamadık.
Session B de Insert, Update işlemleri yapmak isteyelim;
insert into ogretmenler values (4,'volkan');
update ogretmenler set name=’irfan’ where id=2;
Session B de yeni bir kayıt eklemek istediğimizde herhangi bir problem olmadı çünkü row bazlı olarak bir problem yok yeni kayıt eklendi, A session da henüz commit olmayan id=2 kaydı burada da bir değişiklik yapılmak istendiğinde Lock oluştu ve psql komut satırı diğer tarafın commit veya rollback olmasını bekleyecek, bu yüzden bu işlemi cancel yaptık.
Session A
delete from ogretmenler where id=4;
pidimize bakalım
select pg_backend_pid();
Session B
Session B da id=4 olan kaydı Update etmek isteyelim; pidimize bakalım
select pg_backend_pid();
update ogretmenler set name='ferdi' where id=4;
Lock oluştu ve B session ı, Session A nın bu satırlar üzerindeki işlemini bitirmesini bekliyor. Başka bir session üzerinden Lock durumunu kontrol edelim;
Session C
select pid,wait_event_type,wait_event,pg_blocking_pids(pid) from pg_stat_activity where wait_event_type='Lock';
Session C üzerinden hangi id ye sahip oturumun lock'a sebep olduğunu tespit ettik. Locka sebep olan olan oturumu commit ettikten sonra lock ortadan kalktı. Üstte session c de çalıştırdığımız komutu tekrar çalıştırınca boş döndüğünü görebileceğiz.
DEADLOCK
Birden fazla işlemin (transaction) aynı anda birbirinden kaynak bekleyerek sonsuza kadar beklemesi durumudur. Her işlem diğerinin serbest bırakmasını beklediğinden, hiçbiri ilerleyemez ve sistemde tıkanma meydana gelir.
FOR UPDATE Kilidi= Exclusive Lock (X kilidi) oluşturur. Bu satır üzerinde değişiklik yapma veya kilitleme yetkisini yalnızca mevcut transaction'a verir. Diğer transaction'lar bu satırı okurken FOR UPDATE veya FOR SHARE kullanamaz, değiştiremez. Şimdi bir senaryo ile bunu test edelim. Öncelikle bir tablo oluşturup içerisine 2 kayıt ekleyelim.
CREATE TABLE dlock (id int,name nchar(10));
INSERT INTO dlock VALUES (1, 'FB'), (2, 'TS');
Session A
SELECT * FROM dlock WHERE id = 2 FOR UPDATE;
Session B
SELECT * FROM dlock WHERE id = 1 FOR UPDATE;
Session A
SELECT * FROM dlock WHERE id = 2 FOR UPDATE;
Session B
SELECT * FROM dlock WHERE id = 1 FOR UPDATE;
DEADLOCK OLUŞTU. Çünkü A oturumu ilk önce id=2 ile işlem yapmak için satıra x kilidi koydu sonrası B oturumu id=1 ile çalışmak için x kilid koydu. Şuan id=2 A'ya id=1 B'ye ait. Sonrasında A oturumu id=1 ile işlem yapmak istediğinde id=1 B oturumu tarafından kilitli olduğu için A oturumu askıda kaldı. Hemen ardından B oturumu da id=2 ile işlem yapmaya kalkınca bu sefer o da askıda kaldı çünkü id=2'nin üzerinde A oturumunun kilidi var. Böylelikle ikisi de birbirini bekliyor ve deadlock oluşuyor.
Kaynaklar: Faruk Çevik