Daha fazla geliştirici veritabanları hakkında bunu bilmeli

Not. tercüme: Jaana Doğan, Google'da deneyimli bir mühendis olup şu anda şirketin Go'da yazılan üretim hizmetlerinin gözlemlenebilirliği üzerinde çalışmaktadır. İngilizce konuşan kitle arasında büyük bir popülerlik kazanan bu makalede, büyük/zorlu uygulamaların geliştiricilerinin dikkate alması yararlı olan DBMS'lere (ve bazen genel olarak dağıtılmış sistemlere) ilişkin önemli teknik ayrıntıları 17 noktada topladı.

Daha fazla geliştirici veritabanları hakkında bunu bilmeli

Bilgisayar sistemlerinin büyük çoğunluğu durumlarını takip eder ve buna göre bir tür veri depolama sistemi gerektirir. Veri kayıplarına ve kesintilere yol açan tasarım hataları yaparken, uzun bir süre boyunca veritabanları hakkında bilgi biriktirdim. Büyük miktarda bilgiyi işleyen sistemlerde veritabanları sistem mimarisinin kalbinde yer alır ve en uygun çözümün seçilmesinde anahtar unsur olarak görev yapar. Veritabanının çalışmasına çok dikkat edilmesine rağmen, uygulama geliştiricilerin öngörmeye çalıştığı sorunlar genellikle buzdağının sadece görünen kısmıdır. Bu yazı dizisinde bu alanda uzman olmayan geliştiricilere faydalı olacak bazı fikirleri paylaşıyorum.

  1. Ağ %99,999 oranında soruna neden olmuyorsa şanslısınız.
  2. ASİT birçok farklı anlama gelir.
  3. Her veritabanının tutarlılık ve izolasyonu sağlamak için kendi mekanizmaları vardır.
  4. İyimser engelleme, olağan olanı sürdürmenin zor olduğu durumlarda kurtarmaya gelir.
  5. Kirli okumalar ve veri kaybının yanı sıra başka anormallikler de var.
  6. Veritabanı ve kullanıcı her zaman eylemin gidişatı konusunda anlaşamaz.
  7. Uygulama düzeyindeki parçalama, uygulamanın dışına taşınabilir.
  8. Otomatik artış tehlikeli olabilir.
  9. Eski veriler yararlı olabilir ve kilitlenmeleri gerekmez.
  10. Bozulmalar herhangi bir zaman kaynağı için tipiktir.
  11. Gecikmenin birçok anlamı vardır.
  12. Performans gereksinimleri belirli bir işlem için değerlendirilmelidir.
  13. İç içe işlemler tehlikeli olabilir.
  14. İşlemler başvuru durumuna bağlı olmamalıdır.
  15. Sorgu planlayıcıları size veritabanları hakkında çok şey anlatabilir.
  16. Çevrimiçi geçiş zordur ancak mümkündür.
  17. Veritabanındaki önemli bir artış, öngörülemezliğin de artmasını gerektirir.

Bu makalenin önceki bir versiyonuna ilişkin geri bildirimleri için Emmanuel Odeke, Rein Henrichs ve diğerlerine teşekkür etmek istiyorum.

Ağ %99,999 oranında soruna neden olmuyorsa şanslısınız.

Modern ağ teknolojilerinin ne kadar güvenilir olduğu ve sistemlerin ağ arızaları nedeniyle ne sıklıkta çöktüğü sorusu hala devam ediyor. Bu konuyla ilgili bilgi azdır ve araştırmalar genellikle uzmanlaşmış ağlara, ekipmanlara ve personele sahip büyük kuruluşların hakimiyetindedir.

Spanner (Google'ın küresel olarak dağıtılan veritabanı) için %99,999 kullanılabilirlik oranıyla Google, yalnızca %7,6 Sorunlar ağla ilgilidir. Aynı zamanda şirket, uzmanlaşmış ağını yüksek kullanılabilirliğin "ana direği" olarak adlandırıyor. Çalışmak Bailis ve Kingsbury2014 yılında yürütülen “dağıtılmış hesaplamayla ilgili yanlış anlamalar"Peter Deutsch'un 1994 yılında formüle ettiği. Ağ gerçekten güvenilir mi?

Dev şirketlerin dışında, daha geniş İnternet için yürütülen kapsamlı bir araştırma mevcut değil. Ayrıca büyük oyunculardan, müşterilerinin sorunlarının yüzde kaçının ağla ilgili olduğu konusunda yeterli veri yok. Büyük bulut sağlayıcılarının ağ yığınındaki kesintilerin, çok sayıda insanı ve şirketi etkileyen yüksek profilli olaylar olması nedeniyle İnternet'in büyük bir bölümünü birkaç saatliğine kapatabileceğinin çok iyi farkındayız. Ağ kesintileri, bu vakaların tümü gündemde olmasa bile daha birçok durumda soruna neden olabilir. Bulut hizmetlerinin müşterileri de sorunların nedenleri hakkında hiçbir şey bilmiyor. Bir arıza varsa bunu servis sağlayıcıdan kaynaklanan bir ağ hatasına bağlamak neredeyse imkansızdır. Onlar için üçüncü taraf hizmetleri kara kutulardır. Büyük bir hizmet sağlayıcı olmadan etkiyi değerlendirmek imkansızdır.

Büyük oyuncuların sistemleri hakkında bildirdikleri dikkate alındığında, ağ sorunları potansiyel kesinti sorunlarının yalnızca küçük bir yüzdesini oluşturuyorsa şanslı olduğunuzu söylemek yanlış olmaz. Ağ iletişimleri hala donanım arızaları, topoloji değişiklikleri, idari yapılandırma değişiklikleri ve elektrik kesintileri gibi sıradan şeylerden zarar görüyor. Son zamanlarda olası sorunlar listesinin eklendiğini öğrendiğimde şaşırdım. köpekbalığı ısırıkları (evet, doğru duydunuz).

ASİT birçok farklı anlama gelir

ACID kısaltması Atomiklik, Tutarlılık, İzolasyon, Güvenilirlik anlamına gelir. İşlemlerin bu özellikleri, arızalar, hatalar, donanım arızaları vb. durumlarda geçerliliklerini sağlamayı amaçlamaktadır. ACID veya benzeri şemalar olmadan, uygulama geliştiricilerin kendilerinin neden sorumlu olduğu ile veritabanının neden sorumlu olduğunu ayırt etmesi zor olacaktır. İlişkisel işlemsel veritabanlarının çoğu ACID uyumlu olmaya çalışır, ancak NoSQL gibi yeni yaklaşımlar, uygulanması pahalı olduğundan ACID işlemleri olmayan birçok veritabanının ortaya çıkmasına neden olmuştur.

Sektöre ilk girdiğimde teknik liderimiz ASİT konseptinin ne kadar alakalı olduğundan bahsetmişti. Adil olmak gerekirse, ACID katı bir uygulama standardı yerine kaba bir açıklama olarak kabul edilir. Bugün bunu çoğunlukla yararlı buluyorum çünkü belirli bir sorun kategorisine değiniyor (ve bir dizi olası çözüm öneriyor).

Her DBMS ACID uyumlu değildir; Aynı zamanda, ACID'yi destekleyen veritabanı uygulamaları, gereksinimleri farklı şekilde anlıyor. ACID uygulamalarının düzensiz olmasının nedenlerinden biri, ACID gerekliliklerini uygulamak için yapılması gereken birçok ödünleşimden kaynaklanmaktadır. İçerik oluşturucular, veritabanlarını ACID uyumlu olarak sunabilir, ancak uç durumların yorumlanması ve "olası olmayan" olayların ele alınmasına yönelik mekanizmalar önemli ölçüde farklılık gösterebilir. En azından geliştiriciler, temel uygulamaların karmaşıklıkları hakkında üst düzey bir anlayış kazanarak, özel davranışları ve tasarım ödünleşimlerini doğru bir şekilde anlayabilirler.

MongoDB'nin ACID gereksinimlerine uyup uymadığına ilişkin tartışma, sürüm 4'ün yayınlanmasından sonra bile devam ediyor. MongoDB uzun süredir desteklenmiyor Kerestecilik, ancak veriler varsayılan olarak her 60 saniyede bir defadan fazla diske kaydedilmez. Şu senaryoyu hayal edin: Bir uygulama iki yazma işlemi (w1 ve w2) yayınlar. MongoDB w1'i başarıyla saklıyor ancak donanım arızası nedeniyle w2 kayboluyor.

Daha fazla geliştirici veritabanları hakkında bunu bilmeli
Senaryoyu gösteren diyagram. MongoDB diske veri yazamadan çöküyor

Diske kayıt etmek pahalı bir işlemdir. Geliştiriciler, sık sık yapılan kayıtlardan kaçınarak, güvenilirlik pahasına kayıt performansını artırır. MongoDB şu anda günlüğe kaydetmeyi desteklemektedir, ancak günlükler varsayılan olarak her 100 ms'de bir yakalandığından kirli yazmalar yine de veri bütünlüğünü etkileyebilir. Yani, günlükler ve bunlarda sunulan değişiklikler için benzer bir senaryo hala mümkündür, ancak risk çok daha düşüktür.

Her veritabanının kendine ait tutarlılık ve izolasyon mekanizmaları vardır

ACID gereklilikleri arasında tutarlılık ve izolasyon, en fazla sayıda farklı uygulamaya sahiptir çünkü ödünleşim aralığı daha geniştir. Tutarlılık ve izolasyonun oldukça pahalı işlevler olduğu söylenmelidir. Koordinasyon gerektirirler ve veri tutarlılığı için rekabeti artırırlar. Veritabanını birden fazla veri merkezi arasında yatay olarak ölçeklendirmek gerektiğinde (özellikle farklı coğrafi bölgelerde bulunuyorlarsa), sorunun karmaşıklığı önemli ölçüde artar. Kullanılabilirliği azalttığı ve ağ bölümlendirmesini arttırdığı için yüksek düzeyde tutarlılığa ulaşmak çok zordur. Bu olgunun daha genel bir açıklaması için şu adrese bakmanızı tavsiye ederim: CAP teoremi. Ayrıca, uygulamaların küçük miktarlardaki tutarsızlıklarla başa çıkabileceğini ve programcıların, tutarsızlığı işlemek için veritabanına çok fazla güvenmeden, uygulamada ek mantık uygulayacak kadar sorunun nüanslarını yeterince iyi anlayabildiklerini de belirtmekte fayda var.

DBMS'ler genellikle farklı düzeylerde izolasyon sağlar. Uygulama geliştiricileri tercihlerine göre en etkili olanı seçebilirler. Düşük izolasyon, hızın artmasına olanak tanır, ancak aynı zamanda veri yarışı riskini de artırır. Yüksek yalıtım bu olasılığı azaltır, ancak işi yavaşlatır ve rekabete yol açabilir, bu da tabanda arızaların başlamasına neden olacak frenlere yol açacaktır.

Daha fazla geliştirici veritabanları hakkında bunu bilmeli
Mevcut eşzamanlılık modellerinin ve aralarındaki ilişkilerin gözden geçirilmesi

SQL standardı yalnızca dört izolasyon seviyesi tanımlar, ancak teoride ve pratikte çok daha fazlası vardır. Jepson.io Mevcut eşzamanlılık modellerine mükemmel bir genel bakış sunar. Örneğin Google Spanner, saat senkronizasyonu ile harici serileştirilebilirliği garanti eder ve bu daha sıkı bir izolasyon katmanı olmasına rağmen standart izolasyon katmanlarında tanımlanmamıştır.

SQL standardı aşağıdaki izolasyon düzeylerinden bahseder:

  • Serileştirilebilir (en katı ve pahalı): Serileştirilebilir yürütme, bazı sıralı işlem yürütmeyle aynı etkiye sahiptir. Sıralı yürütme, sonraki her işlemin yalnızca bir önceki işlem tamamlandıktan sonra başlaması anlamına gelir. seviyede olduğunu belirtmek gerekir. Serileştirilebilir Anlık görüntü yalıtımının kendisi SQL standardında temsil edilmese de, yorumlamadaki farklılıklar nedeniyle sıklıkla anlık görüntü yalıtımı adı verilen şekilde uygulanır (örneğin, Oracle'da).
  • Tekrarlanabilir okumalar: Geçerli işlemdeki kaydedilmemiş kayıtlar geçerli işlem için kullanılabilir ancak diğer işlemler tarafından yapılan değişiklikler (yeni satırlar gibi) görünmez.
  • Taahhütlü oku: İşlemler için taahhüt edilmemiş veriler mevcut değildir. Bu durumda işlemler yalnızca taahhüt edilen verileri görebilir ve hayali okumalar meydana gelebilir. Bir işlem yeni satırlar ekler ve kaydederse, mevcut işlem sorgulandığında bunları görebilecek.
  • taahhütsüz oku (en az katı ve pahalı seviye): Kirli okumalara izin verilir, işlemler diğer işlemler tarafından yapılan kaydedilmemiş değişiklikleri görebilir. Uygulamada bu düzey, sorgular gibi kaba tahminler için faydalı olabilir. COUNT(*) masanın üstünde.

Seviye Serileştirilebilir Uygulanması en pahalı olan ve sistem üzerinde en yüksek rekabet yüküne neden olan veri yarışları riskini en aza indirir. Diğer izolasyon seviyelerinin uygulanması daha kolaydır ancak veri yarışlarının olasılığını artırır. Bazı DBMS'ler özel bir izolasyon düzeyi belirlemenize izin verir, diğerleri ise güçlü tercihlere sahiptir ve tüm düzeyler desteklenmez.

Yalıtım düzeylerine yönelik destek genellikle belirli bir DBMS'de duyurulur, ancak yalnızca davranışının dikkatli bir şekilde incelenmesi gerçekte ne olduğunu ortaya çıkarabilir.

Daha fazla geliştirici veritabanları hakkında bunu bilmeli
Farklı DBMS'ler için farklı izolasyon seviyelerindeki eşzamanlılık anormalliklerinin incelenmesi

Martin Kleppmann projesinde inziva yeri Farklı yalıtım düzeylerini karşılaştırır, eşzamanlılık anormalliklerinden ve veritabanının belirli bir yalıtım düzeyine uyup uymadığından bahseder. Kleppmann'ın araştırması, veritabanı geliştiricilerinin izolasyon seviyeleri hakkında ne kadar farklı düşündüğünü gösteriyor.

İyimser engelleme, olağan olanı sürdürmenin zor olduğu durumlarda kurtarmaya gelir.

Engelleme, yalnızca veritabanındaki rekabeti arttırdığı için değil, aynı zamanda uygulama sunucularının sürekli olarak veritabanına bağlanmasını gerektirdiği için de çok pahalı olabilir. Ağ bölümlendirmesi, özel kilitleme durumlarını daha da kötüleştirebilir ve tanımlanması ve çözülmesi zor olan kilitlenmelere yol açabilir. Özel kilitlemenin uygun olmadığı durumlarda iyimser kilitleme yardımcı olur.

İyimser kilit bir dizeyi okurken onun sürümünü, sağlama toplamını veya son değişiklik zamanını hesaba katan bir yöntemdir. Bu, bir girişi değiştirmeden önce atomik sürüm değişikliği olmadığından emin olmanızı sağlar:

UPDATE products
SET name = 'Telegraph receiver', version = 2
WHERE id = 1 AND version = 1

Bu durumda tablonun güncellenmesi products Bu satırda daha önce başka bir işlem değişiklik yapmışsa gerçekleştirilmeyecektir. Eğer bu satırda başka bir işlem yapılmadıysa bir satıra ilişkin değişiklik gerçekleşecektir ve güncellemenin başarılı olduğunu söyleyebiliriz.

Kirli okumalar ve veri kaybının yanı sıra başka anormallikler de var

Veri tutarlılığı söz konusu olduğunda, kirli okumalara ve veri kaybına yol açabilecek yarış koşulları potansiyeline odaklanılır. Ancak veri anormallikleri bununla bitmiyor.

Bu tür anormalliklerin bir örneği kayıt distorsiyonudur (eğimli yaz). Bozulmaların tespit edilmesi zordur çünkü genellikle aktif olarak aranmazlar. Bunların nedeni kirli okumalar veya veri kaybı değil, verilere uygulanan mantıksal kısıtlamaların ihlalidir.

Örneğin, bir operatörün her zaman görevde olmasını gerektiren bir izleme uygulamasını ele alalım:

BEGIN tx1;                      BEGIN tx2;
SELECT COUNT(*)
FROM operators
WHERE oncall = true;
0                               SELECT COUNT(*)
                                FROM operators
                                WHERE oncall = TRUE;
                                0
UPDATE operators                UPDATE operators
SET oncall = TRUE               SET oncall = TRUE
WHERE userId = 4;               WHERE userId = 2;
COMMIT tx1;                     COMMIT tx2;

Yukarıdaki durumda, her iki işlemin de başarıyla gerçekleştirilmesi durumunda kayıt bozulması meydana gelecektir. Herhangi bir kirli okuma veya veri kaybı olmamasına rağmen, verilerin bütünlüğü tehlikeye girmiştir: artık iki kişi aynı anda çağrıda kabul edilmektedir.

Serileştirilebilir yalıtım, şema tasarımı veya veritabanı kısıtlamaları, yazma bozulmalarının ortadan kaldırılmasına yardımcı olabilir. Geliştiricilerin üretimde bu tür anormallikleri önlemek için geliştirme sırasında tespit edebilmeleri gerekir. Aynı zamanda, kayıt bozulmalarını kod tabanında aramak son derece zordur. Özellikle büyük sistemlerde, farklı geliştirme ekipleri aynı tablolara dayalı işlevlerin uygulanmasından sorumlu olduğunda ve veri erişiminin özellikleri konusunda anlaşamadıklarında.

Veritabanı ve kullanıcı her zaman ne yapılacağı konusunda anlaşamıyor

Veritabanlarının temel özelliklerinden biri yürütme emrinin garantisidir, ancak bu emrin kendisi yazılım geliştiricisi için şeffaf olmayabilir. Veritabanları işlemleri programcıların amaçladığı sırayla değil, alındıkları sırayla yürütür. Özellikle yüksek yüklü paralel sistemlerde işlemlerin sırasını tahmin etmek zordur.

Geliştirme sırasında, özellikle engellemeyen kütüphanelerle çalışırken, zayıf stil ve düşük okunabilirlik, kullanıcıların işlemlerin sıralı olarak yürütüldüğüne inanmasına neden olabilir, oysa gerçekte veritabanına herhangi bir sırayla ulaşabiliyorlar.

İlk bakışta aşağıdaki programda T1 ve T2 sırayla çağrılıyor ancak bu işlevler bloke edici değilse ve sonucu hemen formda döndürüyorsa söz, daha sonra çağrıların sırası veritabanına girildiği anlara göre belirlenecektir:

sonuç1 = T1() // gerçek sonuçlar vaattir
sonuç2 = T2()

Atomiklik gerekiyorsa (yani, tüm işlemlerin tamamlanması veya iptal edilmesi gerekiyorsa) ve sıra önemliyse, T1 ve T2 işlemleri tek bir işlem içinde gerçekleştirilmelidir.

Uygulama düzeyinde parçalama, uygulamanın dışına taşınabilir

Parçalama, bir veritabanını yatay olarak bölümlendirmenin bir yöntemidir. Bazı veritabanları verileri otomatik olarak yatay olarak bölebilirken bazıları bunu yapamaz veya bu konuda pek iyi değildir. Veri mimarları/geliştiricileri verilere tam olarak nasıl erişileceğini tahmin edebildiklerinde, bu işi veritabanına devretmek yerine kullanıcı alanında yatay bölümler oluşturabilirler. Bu işleme "uygulama düzeyinde parçalama" adı verilir (uygulama düzeyinde parçalama).

Ne yazık ki bu isim çoğu zaman parçalamanın uygulama hizmetlerinde yaşadığı yanılgısına neden oluyor. Aslında veritabanının önünde ayrı bir katman olarak hayata geçirilebilir. Veri büyümesine ve şema yinelemelerine bağlı olarak parçalama gereksinimleri oldukça karmaşık hale gelebilir. Bazı stratejiler, uygulama sunucularını yeniden konuşlandırmak zorunda kalmadan yineleme yeteneğinden yararlanabilir.

Daha fazla geliştirici veritabanları hakkında bunu bilmeli
Uygulama sunucularının parçalama hizmetinden ayrıldığı bir mimari örneği

Parçalamayı ayrı bir hizmete taşımak, uygulamaları yeniden dağıtmaya gerek kalmadan farklı parçalama stratejilerini kullanma yeteneğini genişletir. Vites uygulama düzeyinde böyle bir parçalama sisteminin bir örneğidir. Vitess, MySQL için yatay parçalama sağlar ve istemcilerin MySQL protokolü aracılığıyla ona bağlanmasına olanak tanır. Sistem, verileri birbirleri hakkında hiçbir şey bilmeyen farklı MySQL düğümlerine böler.

Otomatik artış tehlikeli olabilir

AUTOINCREMENT, birincil anahtarlar oluşturmanın yaygın bir yoludur. Veritabanlarının kimlik oluşturucu olarak kullanıldığı ve veritabanının tanımlayıcılar oluşturmak için tasarlanmış tablolar içerdiği durumlar sıklıkla vardır. Otomatik artış kullanarak birincil anahtar oluşturmanın ideal olmaktan uzak olmasının birkaç nedeni vardır:

  • Dağıtılmış bir veritabanında otomatik artış ciddi bir sorundur. Kimliği oluşturmak için genel bir kilit gereklidir. Bunun yerine bir UUID oluşturabilirsiniz: bu, farklı veritabanı düğümleri arasında etkileşim gerektirmez. Kilitlerle otomatik artış, çekişmeye yol açabilir ve dağıtılmış durumlarda kesici uçların performansını önemli ölçüde azaltabilir. Bazı DBMS'ler (örneğin, MySQL), ana-ana çoğaltmanın düzgün şekilde organize edilmesi için özel konfigürasyon ve daha dikkatli olunmasını gerektirebilir. Yapılandırma sırasında hata yapmak kolaydır ve bu da kayıt hatalarına yol açar.
  • Bazı veritabanlarında birincil anahtarlara dayalı bölümleme algoritmaları bulunur. Ardışık kimlikler, öngörülemeyen sıcak noktalara ve bazı bölümlerde yükün artmasına neden olurken diğerleri boşta kalabilir.
  • Birincil anahtar, veritabanındaki bir satıra erişmenin en hızlı yoludur. Kayıtları tanımlamanın daha iyi yolları sayesinde sıralı kimlikler, tablolardaki en önemli sütunu anlamsız değerlerle dolu işe yaramaz bir sütuna dönüştürebilir. Bu nedenle, mümkün olduğunda lütfen genel olarak benzersiz ve doğal bir birincil anahtar seçin (örn. kullanıcı adı).

Bir yaklaşıma karar vermeden önce, otomatik artan kimliklerin ve UUID'lerin indeksleme, bölümleme ve parçalama üzerindeki etkisini göz önünde bulundurun.

Eski veriler yararlı olabilir ve kilitleme gerektirmeyebilir

Çoklu Sürüm Eşzamanlılık Kontrolü (MVCC), yukarıda kısaca tartışılan tutarlılık gereksinimlerinin çoğunu uygular. Bazı veritabanları (örneğin, Postgres, Spanner), işlemleri anlık görüntülerle (veritabanının eski sürümleri) "beslemek" için MVCC'yi kullanır. Tutarlılığı sağlamak için anlık görüntü işlemleri de serileştirilebilir. Eski bir anlık görüntüden okurken güncel olmayan veriler okunur.

Biraz eskimiş verileri okumak, örneğin verilerden analizler oluştururken veya yaklaşık toplam değerleri hesaplarken yararlı olabilir.

Eski verilerle çalışmanın ilk avantajı düşük gecikmedir (özellikle veritabanı farklı coğrafyalara dağıtılmışsa). İkincisi salt okunur işlemlerin kilitsiz olmasıdır. Bu, eski verileri işleyebildikleri sürece çok okuyan uygulamalar için önemli bir avantajdır.

Daha fazla geliştirici veritabanları hakkında bunu bilmeli
Uygulama sunucusu, Pasifik Okyanusu'nun diğer tarafında en son sürüm mevcut olsa bile, 5 saniyelik güncel olmayan verileri yerel kopyadan okur.

DBMS'ler eski sürümleri otomatik olarak temizler ve bazı durumlarda bunu istek üzerine yapmanıza izin verir. Örneğin, Postgres kullanıcıların şunları yapmasına olanak tanır: VACUUM istek üzerine ve ayrıca periyodik olarak bu işlemi otomatik olarak gerçekleştirir. Spanner, bir saatten eski anlık görüntülerden kurtulmak için bir çöp toplayıcı çalıştırıyor.

Herhangi bir zaman kaynağı bozulmaya maruz kalır

Bilgisayar biliminde en iyi saklanan sır, tüm zamanlama API'lerinin yalan söylemesidir. Aslında makinelerimiz şu anki saati tam olarak bilmiyor. Bilgisayarlar, zamanı ölçmek için kullanılan titreşimler üreten kuvars kristalleri içerir. Ancak bunlar yeterince doğru değildir ve tam zamanın ilerisinde/gerisinde olabilir. Vardiya günde 20 saniyeye ulaşabilir. Bu nedenle bilgisayarlarımızdaki saatin periyodik olarak ağdaki saatle senkronize edilmesi gerekir.

Senkronizasyon için NTP sunucuları kullanılır, ancak senkronizasyon işleminin kendisi ağ gecikmelerine tabidir. Aynı veri merkezindeki bir NTP sunucusuyla senkronizasyon bile biraz zaman alır. Halka açık bir NTP sunucusuyla çalışmanın daha da büyük bozulmalara yol açabileceği açıktır.

Atomik saatler ve GPS muadilleri, mevcut zamanı belirlemek için daha iyidir, ancak pahalıdırlar ve karmaşık kurulum gerektirirler, bu nedenle her arabaya kurulamazlar. Bu nedenle veri merkezleri katmanlı bir yaklaşım kullanır. Atomik ve/veya GPS saatleri tam zamanı gösterir ve ardından ikincil sunucular aracılığıyla diğer makinelere yayınlanır. Bu, her makinenin tam zamandan belirli bir kayma yaşayacağı anlamına gelir.

Durum, uygulamaların ve veritabanlarının genellikle farklı makinelerde (farklı veri merkezlerinde olmasa da) bulunması nedeniyle daha da kötüleşiyor. Dolayısıyla zaman yalnızca farklı makinelere dağıtılan veritabanı düğümlerinde farklılık göstermeyecektir. Uygulama sunucusunda da farklı olacaktır.

Google TrueTime tamamen farklı bir yaklaşım benimsiyor. Çoğu kişi Google'ın bu yöndeki ilerlemesinin atomik ve GPS saatlerine sıradan geçişle açıklandığına inanıyor, ancak bu büyük resmin yalnızca bir kısmı. TrueTime şu şekilde çalışır:

  • TrueTime iki farklı kaynak kullanır: GPS ve atom saatleri. Bu saatler birbiriyle ilişkili olmayan arıza modlarına sahiptir. [ayrıntılar için sayfa 5'e bakın burada - yaklaşık. çeviri.), böylece ortak kullanımları güvenilirliği artırır.
  • TrueTime'ın alışılmadık bir API'si var. Zamanı, ölçüm hatası ve belirsizlik içeren bir aralık olarak döndürür. Zamandaki gerçek an, aralığın üst ve alt sınırları arasında bir yerdedir. Google'ın dağıtılmış veritabanı Spanner, geçerli saatin aralık dışında olduğunu söylemek güvenli olana kadar bekler. Bu yöntem, özellikle ana birimlerdeki belirsizlik yüksekse sisteme bir miktar gecikme getirir, ancak küresel olarak dağıtılmış bir durumda bile doğruluğu garanti eder.

Daha fazla geliştirici veritabanları hakkında bunu bilmeli
Spanner bileşenleri TrueTime'ı kullanır; burada TT.now() bir aralık döndürür, böylece Spanner geçerli zamanın belirli bir noktayı geçtiğinden emin olabileceği noktaya kadar uyur.

Geçerli zamanın belirlenmesindeki doğruluğun azalması, Spanner işlemlerinin süresinin artması ve performansın düşmesi anlamına gelir. Bu nedenle tamamen doğru bir saat elde etmek imkansız olsa bile mümkün olan en yüksek doğruluğu korumak önemlidir.

Gecikmenin birçok anlamı var

Bir düzine uzmana gecikmenin ne olduğunu sorarsanız muhtemelen farklı cevaplar alırsınız. DBMS'de gecikmeye genellikle "veritabanı gecikmesi" denir ve istemci tarafından algılanandan farklıdır. Gerçek şu ki, istemci ağ gecikmesi ile veritabanı gecikmesinin toplamını gözlemliyor. Büyüyen sorunların hatalarını ayıklamak için gecikme türünü yalıtabilme yeteneği kritik öneme sahiptir. Metrikleri toplarken ve görüntülerken her zaman her iki türe de dikkat etmeye çalışın.

Belirli bir işlem için performans gereksinimleri değerlendirilmelidir

Bazen bir DBMS'nin performans özellikleri ve sınırlamaları yazma/okuma verimi ve gecikme açısından belirtilir. Bu, temel sistem parametrelerine genel bir bakış sağlar, ancak yeni bir DBMS'nin performansını değerlendirirken, kritik işlemleri (her sorgu ve/veya işlem için) ayrı ayrı değerlendirmek çok daha kapsamlı bir yaklaşımdır. Örnekler:

  • Belirtilen kısıtlamalarla ve ilgili tablolarda satır doldurmayla X tablosuna (50 milyon satırla) yeni bir satır eklerken üretilen iş ve gecikmeyi yazın.
  • Ortalama arkadaş sayısı 500 olduğunda, belirli bir kullanıcının arkadaşlarının arkadaşlarının görüntülenmesinde gecikme.
  • Kullanıcı saatte X girişiyle diğer 100 kullanıcıyı takip ettiğinde, kullanıcının geçmişinden ilk 500 girişin alınmasında yaşanan gecikme.

Veritabanının performans gereksinimlerini karşıladığından emin olana kadar değerlendirme ve denemeler bu tür kritik durumları içerebilir. Benzer bir genel kural, gecikme ölçümlerini toplarken ve SLO'ları belirlerken de bu dökümü dikkate alır.

Her işlem için metrikleri toplarken yüksek önem düzeyine dikkat edin. Yüksek güçlü hata ayıklama verileri elde etmek için günlükleri, olay toplamayı veya dağıtılmış izlemeyi kullanın. Makalede "Gecikmede Hata Ayıklamak İster misiniz?» Gecikme hata ayıklama yöntemlerine aşina olabilirsiniz.

İç içe işlemler tehlikeli olabilir

Her DBMS, iç içe geçmiş işlemleri desteklemez, ancak destekledikleri zaman, bu tür işlemler, tespit edilmesi her zaman kolay olmayan beklenmedik hatalarla sonuçlanabilir (yani, bir tür anormallik olduğu açık olmalıdır).

Bunları algılayıp atlayabilen istemci kitaplıklarını kullanarak iç içe geçmiş işlemleri kullanmaktan kaçınabilirsiniz. İç içe geçmiş işlemlerden vazgeçilemiyorsa, tamamlanan işlemlerin iç içe geçmiş işlemler nedeniyle yanlışlıkla iptal edildiği beklenmeyen durumlardan kaçınmak için bunların uygulanmasına özellikle dikkat edin.

İşlemlerin farklı katmanlarda kapsüllenmesi beklenmedik iç içe geçmiş işlemlere yol açabilir ve kodun okunabilirliği açısından yazarın amacının anlaşılmasını zorlaştırabilir. Aşağıdaki programa bir göz atın:

with newTransaction():
   Accounts.create("609-543-222")
   with newTransaction():
       Accounts.create("775-988-322")
       throw Rollback();

Yukarıdaki kodun çıktısı ne olacaktır? Her iki işlemi de geri mi alacak, yoksa yalnızca iç işlemi mi? Bizim için işlemlerin oluşturulmasını kapsayan birden fazla kitaplık katmanına güvenirsek ne olur? Bu gibi durumları tespit edip iyileştirebilecek miyiz?

Birden fazla işlem içeren bir veri katmanı düşünün (ör. newAccount) zaten kendi işlemlerinde uygulanmaktadır. Bunları kendi işlemi içinde çalışan üst düzey iş mantığının bir parçası olarak çalıştırırsanız ne olur? Bu durumda izolasyon ve tutarlılık ne olurdu?

function newAccount(id string) {
  with newTransaction():
      Accounts.create(id)
}

Bu gibi sonsuz soruların cevabını aramak yerine iç içe geçmiş işlemlerden kaçınmak daha doğru olacaktır. Sonuçta veri katmanınız kendi işlemlerini oluşturmadan üst düzey işlemleri kolaylıkla gerçekleştirebilir. Ek olarak, iş mantığının kendisi de bir işlemi başlatma, üzerinde işlemler gerçekleştirme, bir işlemi gerçekleştirme veya iptal etme yeteneğine sahiptir.

function newAccount(id string) {
   Accounts.create(id)
}
// In main application:
with newTransaction():
   // Read some data from database for configuration.
   // Generate an ID from the ID service.
   Accounts.create(id)
   Uploads.create(id) // create upload queue for the user.

İşlemler başvuru durumuna bağlı olmamalıdır

Bazen belirli değerleri değiştirmek veya sorgu parametrelerinde ince ayar yapmak için işlemlerde uygulama durumunu kullanmak cazip gelebilir. Dikkate alınması gereken kritik nüans, doğru uygulama kapsamıdır. İstemciler genellikle ağ sorunları olduğunda işlemleri yeniden başlatır. İşlem başka bir işlem tarafından değiştirilen bir duruma bağlıysa, veri yarışı olasılığına bağlı olarak yanlış değeri seçebilir. İşlemler, uygulamadaki veri yarışı koşulları riskini dikkate almalıdır.

var seq int64
with newTransaction():
    newSeq := atomic.Increment(&seq)
    Entries.query(newSeq)
    // Other operations...

Yukarıdaki işlem, nihai sonuçtan bağımsız olarak her yürütüldüğünde sıra numarasını artıracaktır. Ağ sorunları nedeniyle taahhüt başarısız olursa, tekrar denediğinizde istek farklı bir sıra numarasıyla yürütülür.

Sorgu planlayıcıları size bir veritabanı hakkında çok şey anlatabilir

Sorgu planlayıcıları bir sorgunun veritabanında nasıl yürütüleceğini belirler. Ayrıca istekleri analiz edip göndermeden önce optimize ederler. Planlamacılar yalnızca ellerindeki sinyallere dayanarak bazı olası tahminler sunabilirler. Örneğin, aşağıdaki sorgu için en iyi arama yöntemi nedir?

SELECT * FROM articles where author = "rakyll" order by title;

Sonuçlar iki şekilde alınabilir:

  • Tam tablo taraması: Tablodaki her girişe bakabilir ve eşleşen yazar adına sahip makaleleri döndürebilir ve ardından sıralayabilirsiniz.
  • Dizin taraması: Eşleşen kimlikleri bulmak, bu satırları almak ve ardından sıralamak için bir dizin kullanabilirsiniz.

Sorgu planlayıcının görevi hangi stratejinin en iyi olduğunu belirlemektir. Sorgu planlayıcıların yalnızca sınırlı tahmin yeteneklerine sahip olduğunu dikkate almakta fayda var. Bu kötü kararlara yol açabilir. DBA'lar veya geliştiriciler bunları, düşük performans gösteren sorguları teşhis etmek ve ince ayar yapmak için kullanabilir. DBMS'nin yeni sürümleri, sorgu planlayıcıları yapılandırabilir ve yeni sürümün performans sorunlarına yol açması durumunda, kendi kendine teşhis, veritabanını güncellerken yardımcı olabilir. Yavaş sorgu günlükleri, gecikme sorunu raporları veya yürütme süresi istatistikleri, optimizasyon gerektiren sorguların belirlenmesine yardımcı olabilir.

Sorgu planlayıcı tarafından sunulan bazı ölçümler gürültüye maruz kalabilir (özellikle gecikme veya CPU süresini tahmin ederken). Zamanlayıcılara iyi bir katkı, yürütme yolunu izlemeye ve izlemeye yönelik araçlardır. Bu tür sorunları teşhis etmenize olanak tanırlar (ne yazık ki, tüm DBMS'ler bu tür araçları sağlamaz).

Çevrimiçi geçiş zor ama mümkün

Çevrimiçi geçiş, canlı geçiş veya gerçek zamanlı geçiş, kesinti veya veri bozulması olmadan bir veritabanından diğerine geçmek anlamına gelir. Geçiş aynı DBMS/motor içinde gerçekleşirse dinamik geçişin gerçekleştirilmesi daha kolaydır. Farklı performans ve şema gereksinimlerine sahip yeni bir DBMS'ye geçmek gerektiğinde durum daha da karmaşık hale gelir.

Farklı çevrimiçi geçiş modelleri vardır. İşte onlardan biri:

  • Her iki veritabanında da çift girişi etkinleştirin. Bu aşamadaki yeni veritabanı tüm verilere sahip değildir, yalnızca en son verileri kabul eder. Bundan emin olduktan sonra bir sonraki adıma geçebilirsiniz.
  • Her iki veritabanından okumayı etkinleştirin.
  • Sistemi, okuma ve yazmanın öncelikli olarak yeni veritabanında gerçekleştirileceği şekilde yapılandırın.
  • Veri okumaya devam ederken eski veritabanına yazmayı bırakın. Bu aşamada yeni veritabanı hala bazı verilerden yoksundur. Eski veritabanından kopyalanmaları gerekir.
  • Eski veritabanı salt okunurdur. Eksik verileri eski veritabanından yenisine kopyalayın. Geçiş tamamlandıktan sonra yolları yeni veritabanına değiştirin ve eskisini durdurup sistemden silin.

Daha fazla bilgi için iletişime geçmenizi öneririm MakaleStripe'ın bu modele dayanan geçiş stratejisinin ayrıntılarını veren.

Veritabanındaki önemli bir artış, öngörülemezliğin de artmasına neden olur

Veritabanının büyümesi, ölçeğiyle ilgili öngörülemeyen sorunlara yol açar. Bir veritabanının iç yapısı hakkında ne kadar çok şey bilirsek, nasıl ölçekleneceğini o kadar iyi tahmin edebiliriz. Ancak bazı anları öngörmek hala imkansızdır.
Taban büyüdükçe, veri hacmi ve ağ bant genişliği gereksinimlerine ilişkin önceki varsayımlar ve beklentiler geçerliliğini yitirebilir. Bu, büyük tasarım revizyonları, büyük ölçekli operasyonel iyileştirmeler, dağıtımların yeniden düşünülmesi veya olası sorunlardan kaçınmak için diğer DBMS'lere geçiş gibi soruların ortaya çıktığı zamandır.

Ancak mevcut veritabanının iç yapısına ilişkin mükemmel bilginin gerekli olan tek şey olduğunu düşünmeyin. Yeni ölçekler yeni bilinmeyenleri de beraberinde getirecek. Tahmin edilemeyen sorunlar, düzensiz veri dağıtımı, beklenmeyen bant genişliği ve donanım sorunları, sürekli artan trafik ve yeni ağ bölümleri sizi veritabanı yaklaşımınızı, veri modelinizi, dağıtım modelinizi ve veritabanı boyutunuzu yeniden düşünmeye zorlayacaktır.

...

Bu makaleyi yayınlamayı düşünmeye başladığımda orijinal listemde zaten beş madde daha vardı. Sonra çok büyük bir sayı geldi yeni fikirler başka nelerin kapsanabileceği hakkında. Bu nedenle makale, maksimum dikkat gerektiren en az belirgin sorunlara değiniyor. Ancak bu, konunun tükendiği anlamına gelmiyor ve bundan sonraki materyallerimde artık bu konuya dönmeyeceğim ve mevcut materyalde değişiklik yapmayacağım.

PS

Blogumuzda da okuyun:

Kaynak: habr.com

Yorum ekle