Gantek
MVCC (Multi Version Concurrency Control) nedir? PostgreSQL’in MVCC implementasyonu nasıldır?

MVCC (Multi Version Concurrency Control) nedir? PostgreSQL’in MVCC implementasyonu nasıldır?

Veritabanı yönetim sistemlerinin, performansın artırılabilmesi için aynı tablo üzerinde işlem yapan birden fazla eş zamanlı sorguyu aynı anda çalıştırması gerekir. PostgreSQL’in en bilinen özelliklerinden biri eş zamanlılığı ve eş zamanlı sorguları birbirini bloke etmeden çalıştırmasıdır. Buradaki temel hedef, tabloya yazma işlemi (UPDATE, INSERT) yapılırken okuma işlemini bloke etmemesidir.

MVCC (Multi Version Concurrency Control) tekniği eş zamanlı sorguların çalıştırıldığı bir anda, sorgularda kullanılan kayıtların birbiriyle çelişmesini engelleyerek, paralelliği artıran genel bir metodolojisidir. Eş zamanlı işlemlere izin veren bütün veritabanı yönetim sistemlerinde kullanılır. İlk olarak MVCC’den David Reed’in 1978 tarihli “Concurrency Control in Distributed Database Systems” başlık doktora tezinde bahsedilmektedir.

 

 

 

MVCC’nin mantığı “güncellenen bir kaydı hemen değiştirme ama kopyasını çıkararak buraya güncel veriyi yaz ancak ihtiyaç olmadığında eski sürümü sil” olarak özetlenebilir. Kaydın eski sürümü belirli bir süre daha tutularak, eş zamanlı işlemlerin kullanımına sunulur. Eğer eski sürüme ihtiyaç duyulmadığında bu kayıt silinir.

MVCC birden fazla tümleşik işlemin aynı kayıtlara kilit (lock) uygulamadan erişmesini sağlar. Bu sebeple, MVCC çok istemcili bir veritabanı ortamında eş zamanlılığı artırarak performansı yükseltir. Tabloların kilitlenmesine veya sorguların seri şekilde birbiri arkasına çalıştırılmasını sağlayan yöntemlere göre paralel çalışma imkânı sağlar. MVCC’de eş zamanlı yazma ve okuma işlemleri bloke edilerek bekletilmez.

Bütün veritabanı yönetim sistemlerinde, MVCC yöntemi çerçevesinde paralel işlemler sırasında güncellenen veya silinen kayıtlar veritabanından silinmez. Silinmek üzere işaretlenir. Bu şekilde bu kaydı silen işlemle (transaction) aynı anlarda başlayan diğer işlemin (transaction) silinen kaydın silinmeden önceki sürümünü görmesi ve kullanması sağlanır.

MVCC implementasyonu her veritabanı yönetim sisteminde farklı şekilde gerçekleştirilir. PostgreSQL’in MVCC implementasyonunun diğer veritabanı yönetim sistemlerine göre bazı sorunları olduğu ve parametre optimizasyonu gerektirdiği bilinir. Michael Stonebraker’in 1987 tarihli tasarım dokümanında, Postgres’in daha ne baştan MVCC’yi destekleyecek şekilde tasarlandığı görülmektedir. Stonebraker, 2003’te ACM’e verdiği röportajda PostgreSQL’in UPDATE edilen bir kaydı silmemek ve yeni sürümünü eklemek üzere ve zaman makinesi gibi bütün veritabanındaki değişikliklerin tutulması için veri yapılarının tasarlandığını anlatmaktadır.

Oracle implementasyonunda, eski sürümler en eskiden en yeniye doğru bir bağlantılı liste (linked list) yapısında bellekte tutularak işlenmektedir. PostgreSQL’de ise eski sürümler sayfalara yazılmakta autovacuum adı verilen bir proses sayesinde ancak belirli bir süre sonra temizlenmektedir. Farklı implementasyon yaklaşımları, UPDATE ve DELETE gibi işlemler için veritabanının performansına etki eder. Örneğin, PostgreSQL’de UPDATE, DELETE ve INSERT komutlar çok hızlı yapılır ama autovacuum prosesi yeterince hızlı değilse, veritabanı sayfaları gereksiz ve silinecek kayıtlarla dolar ve veritabanında “bloat” (şişme) durumu ortaya çıkar. Oracle’da ise eski sürümleri tutmak için bellek kullanıldığından, performans olarak iyi sonuç verirken, PostgreSQL’e göre daha fazla bellek kullanmak zorunda kalır. PostgreSQL’in performansının iyileştirilmesi için autovacuum prosesinin, sistem yüküne göre optimize edilmesi gereklidir.

 

 

PostgreSQL’de her işleme (transaction) sıradan bir ID verilir. Bu ID değerlerine bakarak, hangi işlemin önce başladığı tespit edilebilir. 1256 numaralı tümleşik işlemle birlikte 1258 numaralı işlem benzer anlarda başlamıştır. 1256 numaralı işlem bir kaydı UPDATE işlemiyle güncellemekte ve diğer işlem de kısa bir süre sonra aynı kaydı güncellemeye çalışmaktadır. Böyle bir durumda 1258 numaralı işlem, aslında güncellenmiş kayda değil, tümleşik işlemin başladığı andaki sürümüne erişmelidir. MVCC’nin eski sürümü de tutması sebebiyle 1258 numaralı işlem, kaydın 1256 numaralı işlemden önceki sürümüne erişecektir.

PostgreSQL’in MVCC implementasyonu için, her kayda xmin ve xmax isimli iki gizli kolon eklenir. xmin, bulunduğu kaydın hangi tümleşik işlem tarafından değiştirildiğini gösterir ve içinde transaction ID değeri bulunur. Diğer yandan xmax değeri 0’dan farklıysa, bu kaydın o transaction tarafından silindiğini veya güncellendiğini gösterir. Tablodaki her kayıt içinde ctid isimli bir kolon bulunur ve buradaki değerler, kaydın hangi sayfa ve sayfa içindeki indekste yer aldığını gösterir. Kaydın farklı sürümleri de bir sonraki kayıt sürümünün sayfa no ve indeks değerini tutar. Eğer, bir sorgu kaydın en yeni sürümünü elde etmek isritiyorsa, PostgreSQL indeks boyunca hareket eder ve en son sürümü ede eder.

 

Bir UPDATE işleminden sonra, eski sürüm korunarak yeni sürüm oluşturulur. Bu yeni sürüm, eski sürümün bulunduğu sayfada (mesela sayfa 1901) yer yoksa, diğer bir sayfaya (sayfa 2331) yerleştirilir. MVCC veritabanları, eski ve yeni sürümler arasındaki ilişkiyi tek yönlü bağlantılı listeler (singly linked list) ile yapmak zorundadır çünkü bütün sürümler erişilebilir olmalıdır ve bağlantılı liste daha az yer kaplamalıdır.

 

 

MVCC veritabanlarında aynı mantıksal kaydın birden fazla sürümü bir şekilde birbirine bağlanmalıdır.

Daha az bellek ve zaman harcamak için genellikle tek yönlü bağlantılı liste (singly linked-list) kullanılır.

Veritabanı yönetim sistemi tasarımcıları, tek yönlü bağlantılı listenin yönünün en yeni sürümden eskisine (newest-to-oldest: N2O) mi yoksa en eski sürümden en yenisine (oldest-to-newest: O2N) mi olacağına karar vermelidir.

Oracle, MySQL ve MSSQL N20 yöntemini kullanırken PostgreSQL O2N metodunu uygular. PostgreSQL’in O2N yöntemini kullanmasının bazı dezavantajları vardır. VACUUM ve autovacuum işlemleri son derece önem kazanır.

PostgreSQL’de bir sorgu kaydın en yeni sürümünü sorduğunda, en eski sürümden yenisine doğru giderek, diğer bir deyişle diskten birçok okuma yaparak sonucu üretebilir. Bu durum PostgreSQL’in performansı etkileyen en önemli tasarım sorunlarından biridir. Kayıtların eski sürümleri geçerli olmasa da ve silinmesi gerekse de bu sürüm zinciri (linked list) üzerinden, en eskiden en yeniye doğru gitmek zorunda kalır. Bu da zaman kaybı yaratır.

UPDATE işleminin çok olduğu veritabanı örneklerinde, autovacuum daha sık devreye girmezse, «bloat» olayına daha çok rastlanır. Sürüm zinciri için her kayda t_tcid isimli bir alan eklenir. t_tcid bu kaydın daha yeni sürümünün hangi sayfada ve sayfanın içinde hangi sırada bulunduğunu gösterir.

 

 

 

PostgreSQL’in iki önemli dezavantajı şunlardır:

  • Bir kaydın (tuple) kopyalarının çıkarılması ve sayfaların içine yazıldıktan sonra bunların diskteki dosyalara yazılması durumu elbette ki performansı düşürebilir.
  • PostgreSQL, kaydın en son sürümünü bulurken, zincir şeklinde farklı sayfalarda arama yapar. Bu nedenle disk I/O işlemleri artabilir ve performans azalabilir. Bu durum, özellikle güncellenen (UPDATE) kayıtlarda gözlenir.


PostgreSQL bu tür kopya kayıtları diske yazmamak, yükü artırmamak ve sadece bellekte tutabilmek için HOT (Heap Only Tuples) optimizasyon tekniğini kullanır. Bu optimizasyon tekniği şu koşullarda kullanılır:

  • Eğer değiştirilen eski kaydın bulunduğu 8KB’lık sayfada boş alan bulunuyorsa.
  • Eski kayıtta ve yeni kayıtta, indekslenen kolonlardaki değerler aynıysa (yani indeks bozulmuyorsa)

 

 

 

«Fill factor» yüzde anlamına gelen 0 ile 100 arasında değişen bir yapılandırma parametresidir. 100 tam paketleme anlamına gelir. Küçük «fill factor» verildiğinde, INSERT işlemleri «page»lerin (sayfaların) sadece o kadarını doldurur. Diğer bir deyişle, sayfalarda boş alan bırakılır.

Sayfalarda kayıtlarla doldurulmadan kalan bölüm, daha sonra yapılan UPDATE’lerde o sayfadaki satırların güncellenmesi için kullanılır. Çok güncellenen tablolar için (HOT optimizasyonunu düşünerek) FF’in düşük tutulması (mesela %70 gibi) performansı artırabilir. Ancak, çok yoğun kullanılan tablolarda ise, daha sık diskten okuma yapıldığında performansı düşürdüğü bilinmektedir. Bu nedenle, oluşturulan veri modelinde, FF’in test edilerek uygun bir değer yüklenmesi iyi olur.

 

Linkler

https://ottertune.com/blog/the-part-of-postgresql-we-hate-the-most

https://www.cybertec-postgresql.com/en/what-is-fillfactor-and-how-does-it-affect-postgresql-performance/

https://www.postgresql.org/docs/current/storage-hot.html

 

Güncel Blog Yazıları

Oracle ASR Manager ile Oracle Donanım Arızalarında Otomatik Çağrı  Açılması
Elasticsearch Machine Learning
Gelişmiş Arama Deneyimi: Elasticsearch Relevance Engine ve Büyük Dil Modelleri ile Yapay Zeka Destekli Arama Çözümleri
Kubernetes - Cka Sınavı  Genel Başlıklar
Kubernetes Mimarisi
Openshift Updates
Dell OpenManage Enterprise ile Tek Yerden Çoklu Sistem Yönetimi
Dolandırıcılık Yönetim Sisteminin Önemi ve Bu Kapsamda Kullanılan ROC-Fraud Management System
Partner Settlements’ın Önemi ve Bu Kapsamda Kullanılan ROC-Partner Settlement System
Gelir Güvence Sisteminin Önemi ve Bu Kapsamda Kullanılan ROC-Revenue Assurance System
Windows Admin Center – Kolaylaştırılmış, Modern Uzaktan Sunucu Yönetim Aracı
Mikroservislerin Gelecegi
OpenShift Kurulum Yöntemleri Nelerdir, Hangisini Seçmeliyim?
Veeam Kasten ile Kubernetes Yüklerinizi Koruyun
Türk Telekom’da Uygulama Modernizasyonu ve Açık Kaynak Kullanımı
OpenShift Local, eski adıyla Code Ready Containers Ortamı ve Kullanımı
Compliance with Openscap on Satellite
OpenShift 4.18 MetalLB ile LoadBalancer Servisi
Kubectl Kustomize Eklentisi - Nedir, Nereden Başlanır ?
Dell PowerEdge MX7000: Modern Veri Merkezleri İçin Modüler Mükemmellik
IBM Instana OpenShift Mimari Dönüşüm Projesi
Redis‘te En Sık Yapılan Hatalar
Turbonomic 101
Açık Kaynak Yazılım Lisans Türleri
INSTANA 101
Podman
GitLab 101
CI/CD Nedir?
GitLab’ın AI Yeteneği ve DevSecOps Platformundaki Rolü
2023'te Dijital Yatırımlarımızda Öne Çıkacak Konular
Bulut Teknolojisi Nedir?
Veritas ile Veri Yönetiminde Yenilikçi Yaklaşımlar
API Gateway'ler: Dijital Dönüşümde Verimliliği ve Güvenliği Artırmanın Yolu
Red Hat Ansible Lightspeed ve IBM Watsonx Code Assistant: BT Otomasyonunda Devrim
PostgreSQL’in Tarihçesi
PostgreSQL Mimarisi
Istio Service Mesh
Veri Tabanı Nedir? Veri Tabanı Güvenliğini Nasıl Sağlarız?
DevOps Nedir? DevOps Neden Önemlidir?
PostgreSQL’de TOAST (The Oversized-Attribute Storage Technique) Kavramı
MVCC (Multi Version Concurrency Control) nedir? PostgreSQL’in MVCC implementasyonu nasıldır?