Merhaba arkadaşlar veritabanında Data Concurrency ve Consistency konusunu yazmadan önce aşağıdaki veritabanı yaklaşımlarını öğrenmenin gerekli olduğunu düşünüyorum.

Tutarlılık (Consistency) ve erişilebilirlik (Availability), veri yönetim sistemlerinde iki farklı türde modelin doğmasına sebep olmuştur. Bunlar ACID ve BASE modelleridir.

ACID Modeli

ACID Standartları RDBMS veritabanlarında transaction işlemleri sırasında yapılan işlemlerin ne şekilde yapılması gerektiğini anlatan prensiplerdir. Geleneksel veritabanı ile çalışmış olan hemen hemen herkesin aşina olduğu bir modeldir. Bu modelde çalışan sistemler tutarlılık konusunda son derece hassastır ve veri kaybına oldukça pesimist yaklaşır. ACID, yeteneklerini ortaya dökebilmek için kilit mekanizmalarını kullanır. Bu mekanizmalar verinin diskte ve memoryde tüm kullanıcılar tarafından aynı görünmesini, verinin güncellenmesi sırasında onay gelene kadar tüm istemcilerin bekletilmesini mümkün kılar. Gerekirse tüm veritabanı kilit altına alınır. Gerektiğinde çakışan işlemlerin en maliyetli olanı hariç hepsi iptal edilir. Tabi ki pesimistlik seviyesine müdehale edebilirsiniz. Ancak ACID pesimist olması için dizayn edilmiştir.

Bu yaklaşım, verileri denetim altında tutan lock ve latch mekanizlarını kullanarak veri bütünlüğünü son derece güvenli noktaya taşımıştır. Hızdan daha çok veri tutarlılığının ön planda olduğu, özellikle paraya dokunan işlemler için ACID vazgeçilmezdir.

Aslında ACID; Atomicity, Consistency, Isolation ve Durability kelimelerinin kısaltılmış halidir. Bu ifadeleri inceleyecek olursak;

  • Atomicity : Ya var ya yok prensibidir.  Transaction bütünlüğü içerisindeki işlemlerin ya hepsinin birden gerçekleşmesi ya da bir işlemde hata oluşursa tüm transaction işlemlerinin geri alınarak veritabanının önceki duruma getirilmesidir. Yaptığımız işlem eğer DB’de birden fazla tablo ve/veya kaydı etkiliyorsa değişikliklerden herhangi biri başarısız olduğunda bütün değişikliklerin geri alınmasını isteriz. Tabii eğer bütün değişiklikler başarılı olarak sonuçlandıysa işlemin saklanmasını tercih ederiz. İşte Atomicity özelliği tam olarak bunu garanti eder. DB, işlemleri ya hep ya hiç prensibine göre gerçekleştirir. Klasik olarak örnek verilen A’nın B’ye para transfer etmesi durumunda A’nın hesabından para çekilmesi fakat B’nin hesabına aktarılırken bir hata oluşması durumunda DB, Atomicity özelliği paranın ortada kalmayacağını garanti eder.
  • Consistency : Yapılan işlemin mantıklı ve tutarlı olması prensibidir.Herhangi bir anda veritabanı, veritabanı sistemi üzerinde tanımlanmış tüm kurallar (trigger, constraint,vs.) ile tutarlı durumdadır. Transaction’lar veritabanının bu tutarlı durumunu bozamazlar, bozmaya kalktıklarında iptal edilirler ve veritabanı transaction çalışmaya başlamadan önceki tutarlı durumuna geri getirilir. Her bir işlemin gerçekleştirilmesi sonrasında alınan çıktı, girdi ve yapılan işlemler ile olan tutarlılığını, tanımlanan kurallara uygunluğunu ifade eder. Ben 5 liralık havale yaptım, karşıya 2 lira gitti gibi bir şey söz konusu olamaz. Benden 5 lira eksildiyse karşıda da 5 lira artmalıdır.
  • Isolation : İşlemin diğer işlemlerden izole olması prensibidir. Isolation, DB üzerinde eş zamanlı gerçekleşen işlemlerin birbirleri ile çakışmadan birbiri ardına -belirlenen öncelik sırasına göre- işletilmesini sağlar. Örnek vermek gerekirse; İki farklı işlem üzerinden DB’deki aynı satırda, içeriği 3 olan kolon 1’er artırılmak istensin. DB, Isolation özelliği sayesinde aynı anda gelen bu işlemleri sıraya sokarak önce 3’ü 1 artırarak kolonu 4’e, sonra da 4’ü yine 1 artırarak kolonun değerini 5’e günceller. Böylece DB işlemleri birbirinden izole ederek hepimizin bildiği “Race Condition”ı engellemiş olur. Burada Isolation özelliği olmasaydı DB, 3 değeri ile başlayıp iki artırımı paralel gerçekleştirip kolonu hatalı bir şekilde 4’e güncelleyebilirdi.
  • Durability : Yapılan işlemlerin kalıcı olduğunu ifade eden prensiptir.Durability özelliği sayesinde DB bir Transaction tamamlandıktan sonra her ne olursa olsun bu Transaction’ın kaybolmayacağını ve bozulmayacağını garanti eder. RDBMS’ler açısından bunu sağlamak oldukça zor olmakla birlikte bunu genellikle başarılı bir şekilde yerine getirirler. İşlemin zorluğu Transaction’ın gerçekleştiği Memory (RAM) ile kayıt altına alındığı Disk arasındaki senkronizasyon ve olası problemlerden (disk bozulması, elektrik kesilmesi) ileri gelmektedir.

Isolation seviyesi,bir transaction tarafından lock’lanan veri sayısını dolayısı ile veritabanının eşzamanlı çalışma seviyesini yani veritabanının bir anlamda hızını belirler. Dolayısı ile Isolation seviyesi ve eşzamanlılık (concurrency) arasında bir trade-off vardır. Isolation ne kadar sıkıysa eşzamanlılık o kadar düşüktür, veritabanı bir o kadar yavaşlar.Özet olarak ACID tutarlılık konusunda çok güçlüdür. Ancak kilit mekanizları çok fazla denetim yaptığı için sistemleri hız konusunda oldukça zayıf düşürmektedir. Geleneksel veritabanlarında (RDBMS) sıkça karşılan bir durum.

BASE Modeli

Yatay ölçeklenmiş sistemlerde karşımıza çıkan bu modelde ACID’de olduğu gibi kilit mekanizmaları yer almaz. Tutarlılık konusunda son derece optimist bir yaklaşım söz konusudur. Bazı teknikler sayesinde tutarlı bir sistem kurulabilse de bu modelde asıl önemli olan taleplere hızla cevap verebilmektir. Sistemin büyüklüğüne ve sağlık durumuna bağlı olarak veri tutarlılığı yerlerde sürünebilir. Bir makinede arkadaşlık isteğini kabul ettiğiniz kişiye diğer makineden hemen baktığınızda isteğinin kabul edilmemiş olduğunu görmeniz muhtemel. Tabi ki kısa bir süre sonra onay tüm cihazlardan görünür hale gelir.
BASE, “Basically Available Soft-state services with Eventual-consistency” ibaresini ifade eder.

Yani, sürekli ayakta olan bu sistem kullanıcıların isteklerine hızla cevap verir. Veri tutarlılığını garanti etmez. Bir süre sonra veriler tüm sistemde tutarlı duruma gelir. Tutarlılık sağlanana kadar talebin yönlendiği cihazın elinde ne varsa istemciye o iletilir.

Yukarıdaki ibaredeyi ele alırsak;

  • Basic Availability :Sistem CAP teoremine uygun olarak sürekli çalışır. Her bir talebe cevap verir. Fakat bu zorunluluk bir hata durumunda bile geçerli olduğu için veri tutarlılığını garanti etmez ve tüm veriye erişimi mümkün kılmaz. Yani bir nevi verinin bir kısmından feragat etmek suretiyle daha basit bir erişilebilirlik hizmeti almış olursunuz.
  • Soft State: Verileri yazılır ancak tutarlı olmayabilir. Bu developerin görevi olarak görünür. Ayrıca veriler tüm cihazlarda aynı şekilde görünmesi garanti edilmez.
  • Eventualy Consistency:İşlemlerin etkileri sistemin durumuna bağlı olarak ancak bir süre sonra diğer cihazlara yansır. Yani neredeyse tutarlı bir sistem.

Kim bu modelde çalışmak ister ki demeyin. Günlük hayatta her yanımızı saran  sosyal medya bu model sayesinde milyonlara hizmet verebilmektedir. Birbirine bağlı binlerce cihazdan yüzlercesi gün içinde arızalanır. Fakat hizmet kesintisiz devam eder.

CAP Teoremi : CAP teoremi özellikle dağıtık (distributed) sistemlerle uğraşanların aşina olduğu bir terimdir. CAP teoremi, dağıtık bir sistemin aynı anda tutarlılık (consistency), ulaşılabilirlik (availability) ve bölünebilme toleransı (partition tolerance) koşullarına aynı anda sahip olamayacağını söyler. Yani bunlardan sadece ikisini tercih etmek durumundasınız. Teorem, ilk olarak 1998 yılında California üniversitesinde bilgisayar bilimcisi Eric Brewer tarafından ortaya atılmıştır.

Yukarıda ACID ve BASE modellerinin varsayılan çalışma şekillerini anlattık. ACID modeli içerisinde “Isolation Level” tercihi çalışma şeklinizi BASE modeline benzetmenize olanak tanır. Benzer şekilde BASE modelindeki çalışma şekliniz de master kullanımı, kendi yazdığını okuma ve oy çokluğu gibi teknikler sayesinde ACID modeline benzetilebilir.
Yani bazı konfigrasyonlar sayesinde modeller birbirine yakınsayabilir. Ancak BASE yatay ölçeklenebilen NoSQL dünyasının, ACID ise dikey ölçeklenebilen geleneksel RDBMS dünyasının felsefesidir.

ACID Yaklaşımında Isolation

Kurduğumuz sistemin iş kurallarına göre veri tabanı tabloları üzerinde yapılan işlemlerin birbirinden katı bir şekilde izole edilmesi gerekmeyebilir. Örneğin bir Dashboard’da sistemdeki toplam kullanıcı sayısını göstermek üzere yaptığımız bir sorgunun, performans gerekçesiyle aynı anda sisteme yeni bir kullanıcıyı dahil etmek için koşturduğumuz bir Transaction’dan etkilenmemesini isteyebiliriz. Buna karşın yine iş kuralları çerçevesinde, Dashboard’da anlık olarak muhakkak gerçek değeri vermemiz gerektiğinde, yeni kullanıcıyı sisteme dahil eden Transaction’ın toplam kullanıcı sayısını verecek sorguyu etkilemesini de isteyebiliriz.

Farklı ihtiyaçlara göre, kullanıcılar ve RDBMS arasında bir protokol oluşturmak üzere, SQL Standardında 4 izolasyon seviyesi Serializable, Repeatable Read, Read Committed ve Read Uncommitted olarak tanımlanmıştır. Verilen Transaction Isolation Level’leri somutlaştırmak ve seçimi kolaylaştırmak adına literatürde genel olarak 3 durum verilir ve iş ihtiyaçlarınızın bu durumlara uygunluğuna göre Transaction’larınızda ilgili izolasyon seviyesini seçmeniz beklenir.

  • Dirty Read : Bir başkası tarafından (bir başkasının transaction’ı tarafından) henüz commit edilmemiş verinin, diğer kullanıcının transaction’ı tarafından okunmasına denir.Bir Transaction’ın aynı anda işletilmekte olan başka bir Transaction bitmeden o Transaction’ın etki ettiği dataları okuyabilmesi anlamına gelir (yukarıda verilen ilk Dashboard örneği). Eş zamanlı olarak çalışan Transaction’ lardan birisi, diğerinin okuduğu aynı veriler üzerinde değişiklik yapar. Aynen Non-Repeatable Read’ e neden olan durumda olduğu gibi. Ancak önemli bir fark vardır. Değişiklik yapan Transaction Commit edilmeden, diğer Transaction aynı satırıları tekrar okur ve değişiklikleri görür. Bu andan sonra, değişiklikleri yapan Transaction yaptığı güncellemeleri RollBack ile geri alır. İşte bu noktada, verileri okuyan Transaction’ da geri alınmış (RollBack) yani veri tabanına yansıtılmamış değişiklikler halen daha var olacaktır ki aslında bu değişiklikler mevcut değildir. İşte bu durum Dirty-Reads olarak adlandırılır. Ancak burada söz konusu olan Transaction’ lar eş zamanlı çalışmakla birlikte, birisi Commit veya RollBack edilmeden diğerininde veri çekme gibi işlemleri yapabilmesine izin veren yapıdadırlar.

A transaction’ı başlar

UPDATE employee SET salary = 31650WHERE empno = '000090';

B transaction’ı başlar

SELECT * FROM employee;

A transaction’ı commit göndermemiş olmasına rağmen, B transaction’ı A’nın yaptığı değişiklikleri görür.

  • Nonrepeatable Read : Bir Transaction’ın aynı kaydı iki kere okuduğunda farklı değerler (ilk okumadan sonra sonlanan başka bir Transaction’dan dolayı) elde edebileceği anlamına gelir. İki eş zamanlı çalışan Transaction’ ımız olduğunu düşünelim. Transaction’ lardan birisi veri çekmiş olsun. Özellikle çektiği belirli bir satır olabilir. Diğer Transaction’ da bu belirli satırı veya başkalarını güncellesin ve işlemi onaylansın (Commit). İşte bu noktadan sonra, diğer çalışmakta olan Transaction aynı satırlara yeniden baktığında verilerin değişmiş olduğunu görecektir. İşte bu satırlardaki ani ve bilinmeyen değişiklikler nedeni ile, bu durum Non-Repeatable Read olarak adlandırılmıştır.

A transaction’ı başlar

SELECT * FROM employee WHERE empno = '000090' ;

B transaction’ı başlar

UPDATE employee SET salary = 30100 WHERE empno = '000090';
COMMIT;

B transaction’ı A transaction’ının okumuş olduğu veriyi güncellemiştir. Eğer A transaction’ında tekrar aynı sorgu çalıştırılırsa farklı bir değer okunacaktır. Daha kötüsü, eğer A sorgusunda okunan değer belli işlemlerden geçirilip tabloya update edilmek istenirse, B transaction’ının yaptığı değişiklik hesaba katılmadan ezilecektir.

  • Phantom Read : Bir Transaction’ın ilk yaptığı sorgudan dönen kayıtların aynı sorguyu aynı Transaction içerisinde ikinci kez yapması ile farklı sayıda kayıt (yine ilk sorgudan sonra başka Transaction tarafından tabloya eklenen kayıtlar dolayısıyla) dönebilmesi anlamına gelir. İki Transaction olduğunu ve bunların eş zamanlı olarak çalıştığını düşünelim. Transaction 1, veri tabanından her hangi bir tabloya ait belirli bir veri kümesini çekmiş olsun. Aynı veri kümesine Transaction 2′ ninde baktığını düşünelim. Transaction 2, tabloya yeni satırlar girsin ve Transaction’ ı onaylansın(Commit). Bu noktadan sonra, halen daha çalışan Transaction1, aynı veri kümesini tekrardan Transaction içerisinde talep ettiğinde, yeni eklenmiş satırlar olduğunu görecektir. Bu satırlar, hayalet olarak düşünülür ve bu nedele Phantom olarak adlandırılır. Çünkü, Transaction1 işlemini sonlandırmadan veri kümesinin yeni bir şekline sahip olmuştur. Yeni eklenen satırlar onun için bir anda ortaya çıkan hayalet satırlar gibidir.

A transaction’ı başlar

SELECT * FROM employee WHERE salary > 30000;

B transaction’ı başlar

INSERT INTO employee(empno, firstnme,lastname, job,salary) VALUES ('000350', 'JOHN','LOCK','DBA',35000);
COMMIT;

B transaction’ı A transaction’ının sorgu aralığına giren kayıtlar insert etmiştir. A transaction’ı tekrar çalıştırıldığında eski okuduğu kayıtlar değişmemiş olsa da, yeni kayıtlar da okuyacaktır. Dolayısı ile A’nın iki sorgusu birbiri ile aynı değildir.

Uygulamamızın yukarıdaki üç duruma tahammül edip edemeyeceğine göre aşağıdaki tablodan Transaction Isolation Level belirlenir.

RDBMS’ler ilgili izolasyon seviyesinin vadettiği garantileri sağlamak için DB üzerindeki kayıt veya kayıtlarda locklar tutar. Bu lockların RDBMS’in eş zamanlı işlem yapmasını engellediği ve dolayısıyla scale etmesine engel olduğundan bahsetmiştik.

Kaynaklar
https://medium.com/@gokhansengun
http://www.sqlserveronculeri.com/1/Article/4832/nosql-dunyasi—2-(veri-tutarlilik-modelleri-acid-vs-base).aspx
https://towardsdatascience.com/cap-theorem-and-distributed-database-management-systems-5c2be977950e
https://www.buraksenyurt.com/post/Transaction-larda-Izolasyon-Seviyeleri-(Isolation-Level)-1-bsenyurt-com-dan
https://blogs.oracle.com/oraclemagazine/on-transaction-isolation-levels

 

Mustafa Bektaş Tepe

İyi Çalışmalar

1,512 total views, 6 views today