InterSystems IRIS globallerindeki işlemler

InterSystems IRIS globallerindeki işlemlerInterSystems IRIS DBMS, veri depolamaya yönelik ilginç yapıları (global yapıları) destekler. Temel olarak bunlar, işlemler şeklinde çeşitli ek özelliklere sahip çok seviyeli anahtarlar, veri ağaçlarında geçiş için hızlı işlevler, kilitler ve kendi ObjectScript dilidir.

Küreseller hakkında daha fazlasını “Küreseller veri depolamak için kullanılan hazine kılıçlarıdır” başlıklı makale dizisinden okuyun:

Ağaçlar. Bölüm 1
Ağaçlar. Bölüm 2
Seyrek diziler. Bölüm 3

Globallerde işlemlerin nasıl uygulandığı, hangi özelliklerin olduğu ilgimi çekmeye başladı. Sonuçta bu, veri depolamak için normal tablolardan tamamen farklı bir yapıdır. Çok daha düşük seviye.

İlişkisel veritabanları teorisinden bilindiği gibi, işlemlerin iyi bir şekilde uygulanmasının gereksinimleri karşılaması gerekir. ASİT:

A - Atomik (atomiklik). İşlemde yapılan tüm değişiklikler veya hiç değişiklik kaydedilmez.

C - Tutarlılık. Bir işlem tamamlandıktan sonra veritabanının mantıksal durumu dahili olarak tutarlı olmalıdır. Bu gereklilik birçok yönden programcıyı ilgilendirir, ancak SQL veritabanları söz konusu olduğunda yabancı anahtarları da ilgilendirir.

I - İzole edin. Paralel olarak yürütülen işlemler birbirini etkilememelidir.

D - Dayanıklı. Bir işlemin başarılı bir şekilde tamamlanmasının ardından daha düşük düzeydeki sorunlar (örneğin elektrik kesintisi), işlem tarafından değiştirilen verileri etkilememelidir.

Globaller ilişkisel olmayan veri yapılarıdır. Çok sınırlı donanımda süper hızlı çalışacak şekilde tasarlandılar. Küresel işlemlerde işlemlerin uygulanmasına şunu kullanarak bakalım: resmi IRIS liman işçisi görüntüsü.

IRIS'teki işlemleri desteklemek için aşağıdaki komutlar kullanılır: BAŞLAT, TCOMMIT, GERİ DÖNÜŞ.

1. Atomiklik

Kontrol etmenin en kolay yolu atomikliktir. Veritabanı konsolundan kontrol ediyoruz.

Kill ^a
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TCOMMIT

Sonra şu sonuca varıyoruz:

Write ^a(1), “ ”, ^a(2), “ ”, ^a(3)

Biz alırız:

1 2 3

Herşey yolunda. Atomiklik korunur: tüm değişiklikler kaydedilir.

Görevi karmaşıklaştıralım, bir hata oluşturalım ve işlemin kısmen veya hiç kaydedilmediğini görelim.

Atomikliği tekrar kontrol edelim:

Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3

Daha sonra konteyneri zorla durduracağız, fırlatacağız ve göreceğiz.

docker kill my-iris

Bu komut, işlemi hemen durdurmak için bir SIGKILL sinyali gönderdiğinden neredeyse zorla kapatmaya eşdeğerdir.

Belki işlem kısmen kaydedilmiştir?

WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)

- Hayır, hayatta kalmadı.

Geri alma komutunu deneyelim:

Kill ^A
TSTART
Set ^a(1) = 1
Set ^a(2) = 2
Set ^a(3) = 3
TROLLBACK

WRITE ^a(1), ^a(2), ^a(3)
^
<UNDEFINED> ^a(1)

Hiçbir şey hayatta kalmadı.

2. Tutarlılık

Global tabanlı veritabanlarında anahtarlar da global üzerinde yapıldığından (globalin veri depolamak için ilişkisel tabloya göre daha düşük seviyeli bir yapı olduğunu hatırlatmama izin verin), tutarlılık gereksinimini karşılamak için anahtarda bir değişiklik yapılması gerekir. küreseldeki bir değişiklikle aynı işlemde.

Örneğin, içinde kişilikleri sakladığımız ve TIN'i anahtar olarak kullandığımız global bir kişimiz var.

^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
...

Soyadı ve adına göre hızlı arama yapabilmek için ^index anahtarını yaptık.

^index(‘Kamenev’, ‘Sergey’, 1234567) = 1

Veritabanının tutarlı olması için kişiliği şu şekilde eklemeliyiz:

TSTART
^person(1234567, ‘firstname’) = ‘Sergey’
^person(1234567, ‘lastname’) = ‘Kamenev’
^person(1234567, ‘phone’) = ‘+74995555555
^index(‘Kamenev’, ‘Sergey’, 1234567) = 1
TCOMMIT

Buna göre, silerken ayrıca bir işlem kullanmalıyız:

TSTART
Kill ^person(1234567)
ZKill ^index(‘Kamenev’, ‘Sergey’, 1234567)
TCOMMIT

Yani tutarlılık gereksinimini karşılamak tamamen programcının omuzlarındadır. Ancak küreseller söz konusu olduğunda, düşük seviyeli doğaları nedeniyle bu normaldir.

3. İzolasyon

Vahşi doğanın başladığı yer burasıdır. Birçok kullanıcı aynı anda aynı veritabanı üzerinde çalışarak aynı verileri değiştirir.

Bu durum, birçok kullanıcının eş zamanlı olarak aynı kod deposuyla çalışması ve aynı anda birçok dosyada değişiklik yapmaya çalışmasıyla karşılaştırılabilir.

Veritabanı her şeyi gerçek zamanlı olarak çözmelidir. Ciddi şirketlerde sürüm kontrolünden (dalların birleştirilmesi, çakışmaların çözülmesi vb.) sorumlu özel bir kişinin bile bulunduğu ve veritabanının tüm bunları gerçek zamanlı olarak yapması gerektiği dikkate alındığında, görevin karmaşıklığı ve yapılan işlemin doğruluğu göz önüne alındığında, veritabanı tasarımı ve ona hizmet eden kod.

Veritabanı, kullanıcılar aynı veri üzerinde çalışıyorsa, çakışmaları önlemek amacıyla gerçekleştirilen eylemlerin anlamını anlayamaz. Yalnızca diğeriyle çakışan bir işlemi geri alabilir veya bunları sırayla yürütebilir.

Diğer bir sorun ise, bir işlemin yürütülmesi sırasında (taahhütten önce), veritabanının durumunun tutarsız olabilmesidir, dolayısıyla ilişkisel veritabanlarında elde edilen, diğer işlemlerin veritabanının tutarsız durumuna erişiminin olmaması arzu edilir. birçok yönden: anlık görüntüler oluşturma, çoklu sürüm satırları vb.

İşlemleri paralel yürütürken birbirini engellememesi bizim için önemli. Bu izolasyonun özelliğidir.

SQL 4 izolasyon seviyesi tanımlar:

  • TAMAMLANMADI OKUYUN
  • TAMAMLANDI OKUYUN
  • TEKRARLANABİLİR OKUMA
  • SERİLEŞTİRİLEBİLİR

Her seviyeye ayrı ayrı bakalım. Her seviyeyi uygulamanın maliyeti neredeyse katlanarak artıyor.

TAMAMLANMADI OKUYUN - bu en düşük izolasyon seviyesidir, ancak aynı zamanda en hızlısıdır. İşlemler birbirleri tarafından yapılan değişiklikleri okuyabilir.

TAMAMLANDI OKUYUN bir uzlaşma olan izolasyonun bir sonraki seviyesidir. İşlemler, taahhütten önce birbirlerinin değişikliklerini okuyamaz, ancak taahhütten sonra yapılan değişiklikleri okuyabilirler.

T1 ile aynı verilerle çalışan T2, T3 ... Tn işlemlerinde taahhütlerin gerçekleştiği uzun bir T1 işlemimiz varsa, o zaman T1'de veri talep ederken her seferinde farklı bir sonuç elde edeceğiz. Bu olguya tekrarlanamayan okuma denir.

TEKRARLANABİLİR OKUMA — bu izolasyon seviyesinde, her veri okuma isteği için sonuç verilerinin bir anlık görüntüsünün oluşturulması ve aynı işlemde yeniden kullanıldığında anlık görüntüdeki veriler nedeniyle tekrarlanamayan okuma olgusuna sahip değiliz. kullanıldı. Ancak bu izolasyon seviyesinde fantom verileri okumak mümkündür. Bu, paralel olarak taahhüt edilen işlemler tarafından eklenen yeni satırların okunması anlamına gelir.

SERİLEŞTİRİLEBİLİR — en yüksek yalıtım seviyesi. Bir işlemde herhangi bir şekilde kullanılan (okunması veya değiştirilmesi) verinin, ancak ilk işlemin tamamlanmasından sonra diğer işlemlerde kullanılabilir hale gelmesiyle karakterize edilir.

İlk olarak, bir işlemdeki işlemlerin ana iş parçacığından izolasyonunun olup olmadığını anlayalım. 2 adet terminal penceresi açalım.

Kill ^t

Write ^t(1)
2

TSTART
Set ^t(1)=2

İzolasyon yok. Bir iş parçacığı, işlemi açan ikinci iş parçacığının ne yaptığını görür.

Bakalım farklı iş parçacıklarındaki işlemler içlerinde neler olup bittiğini görüyor mu?

2 terminal penceresi açalım ve paralel olarak 2 işlem açalım.

kill ^t
TSTART
Write ^t(1)
3

TSTART
Set ^t(1)=3

Paralel işlemler birbirlerinin verilerini görür. Böylece en basit ama aynı zamanda en hızlı izolasyon seviyesine sahip olduk: KABUL EDİLMEDEN OKUYUN.

Prensipte bu, performansın her zaman öncelikli olduğu küresel şirketler için beklenebilir.

Küresel operasyonlarda daha yüksek düzeyde izolasyona ihtiyacımız olursa ne olur?

Burada izolasyon düzeylerine neden ihtiyaç duyulduğunu ve bunların nasıl çalıştığını düşünmeniz gerekir.

En yüksek izolasyon seviyesi olan SERIALİZE, paralel olarak yürütülen işlemlerin sonucunun sıralı yürütmeye eşdeğer olduğu anlamına gelir ve bu da çarpışmaların olmamasını garanti eder.

Bunu ObjectScript'teki birçok farklı kullanıma sahip akıllı kilitleri kullanarak yapabiliriz: komutla düzenli, artımlı, çoklu kilitleme yapabilirsiniz. KİLİT.

Daha düşük izolasyon seviyeleri, veritabanı hızını artırmak için tasarlanmış ödünlerdir.

Kilitleri kullanarak farklı izolasyon seviyelerini nasıl elde edebileceğimizi görelim.

Bu operatör, yalnızca verileri değiştirmek için gereken özel kilitleri değil, aynı zamanda okuma işlemi sırasında diğer işlemler tarafından değiştirilmemesi gereken verileri okumaları gerektiğinde birkaç iş parçacığını paralel olarak alabilen paylaşılan kilitler olarak adlandırılan kilitleri de almanıza olanak tanır.

İki aşamalı engelleme yöntemi hakkında Rusça ve İngilizce olarak daha fazla bilgi:

İki fazlı engelleme
iki fazlı kilitleme

Buradaki zorluk, bir işlem sırasında veritabanının durumunun tutarsız olabilmesi, ancak bu tutarsız verilerin diğer işlemler tarafından görülebilmesidir. Bundan nasıl kaçınılır?

Kilitleri kullanarak veritabanının durumunun tutarlı olacağı görünürlük pencereleri oluşturacağız. Ve kararlaştırılan durumun bu tür görünürlük pencerelerine tüm erişim, kilitlerle kontrol edilecektir.

Aynı verilerdeki paylaşılan kilitler yeniden kullanılabilir; birkaç işlem bunları gerektirebilir. Bu kilitler diğer işlemlerin verileri değiştirmesini engeller; tutarlı veritabanı durumuna sahip pencereler oluşturmak için kullanılırlar.

Veri değişiklikleri için özel kilitler kullanılır; böyle bir kilidi yalnızca bir işlem alabilir. Özel bir kilit şu şekilde alınabilir:

  1. Verilerin ücretsiz olması durumunda herhangi bir işlem
  2. Yalnızca bu veriler üzerinde paylaşılan bir kilit bulunan ve özel bir kilit isteyen ilk işlem oldu.

InterSystems IRIS globallerindeki işlemler

Görünürlük penceresi ne kadar dar olursa, diğer işlemlerin de o kadar uzun süre beklemesi gerekir, ancak içindeki veritabanının durumu da o kadar tutarlı olabilir.

READ_COMMITTED — Bu seviyenin özü, yalnızca diğer iş parçacıklarından gelen taahhütlü verileri görmemizdir. Başka bir işlemdeki veriler henüz taahhüt edilmemişse eski versiyonunu görürüz.

Bu, kilidin açılmasını beklemek yerine işi paralelleştirmemize olanak tanır.

Özel hileler olmadan IRIS'teki verilerin eski versiyonunu göremeyeceğiz, bu yüzden kilitlerle yetinmek zorunda kalacağız.

Buna göre verilerin yalnızca tutarlılık anlarında okunmasına izin vermek için paylaşılan kilitler kullanmak zorunda kalacağız.

Diyelim ki birbirine para aktaran bir kullanıcı tabanımız var.

123. kişiden 242. kişiye aktarım anı:

LOCK +^person(123), +^person(242)
Set ^person(123, amount) = ^person(123, amount) - amount
Set ^person(242, amount) = ^person(242, amount) + amount
LOCK -^person(123), -^person(242)

Borçlandırmadan önce 123 numaralı kişiden para miktarını talep etme anına özel bir bloke eşlik etmelidir (varsayılan olarak):

LOCK +^person(123)
Write ^person(123)

Hesap durumunu kişisel hesabınızda göstermeniz gerekiyorsa, paylaşılan kilidi kullanabilir veya hiç kullanmayabilirsiniz:

LOCK +^person(123)#”S”
Write ^person(123)

Ancak veritabanı işlemlerinin neredeyse anında yapıldığını varsayarsak (globallerin ilişkisel tabloya göre çok daha alt düzey bir yapı olduğunu hatırlatayım), o zaman bu düzeye olan ihtiyaç azalır.

TEKRARLANABİLİR OKUMA - Bu izolasyon seviyesi, eşzamanlı işlemlerle değiştirilebilecek birden fazla veri okunmasına olanak tanır.

Buna göre değiştirdiğimiz verilerin okunmasına ortak kilit, değiştirdiğimiz verilere ise özel kilitler koymamız gerekecek.

Neyse ki, LOCK operatörü, çok sayıda olabilecek tüm gerekli kilitleri tek bir ifadede ayrıntılı olarak listelemenize olanak tanır.

LOCK +^person(123, amount)#”S”
чтение ^person(123, amount)

diğer işlemler (şu anda paralel iş parçacıkları ^kişiyi(123, miktarı değiştirmeye çalışır, ancak yapamaz)

LOCK +^person(123, amount)
изменение ^person(123, amount)
LOCK -^person(123, amount)

чтение ^person(123, amount)
LOCK -^person(123, amount)#”S”

Kilitleri virgülle ayırarak listelerken sırayla alınırlar ancak bunu yaparsanız:

LOCK +(^person(123),^person(242))

daha sonra hepsi bir kerede atomik olarak alınırlar.

serialize — sonuçta ortak verilere sahip tüm işlemlerin sırayla yürütülmesi için kilitler ayarlamamız gerekecek. Bu yaklaşım için çoğu kilit özel olmalı ve performans için dünyanın en küçük alanlarına alınmalıdır.

Küresel ^kişide fonların borçlandırılması hakkında konuşursak, o zaman bunun için yalnızca SERIALİZE izolasyon düzeyi kabul edilebilir, çünkü paranın kesinlikle sırayla harcanması gerekir, aksi takdirde aynı tutarı birkaç kez harcamak mümkündür.

4. Dayanıklılık

Kullanarak kabın sert kesilmesiyle testler yaptım

docker kill my-iris

Taban onları iyi tolere etti. Herhangi bir sorun tespit edilmedi.

Sonuç

Globaller için InterSystems IRIS'in işlem desteği vardır. Gerçekten atomik ve güvenilirler. Globallere dayalı bir veritabanının tutarlılığını sağlamak için, yabancı anahtarlar gibi karmaşık yerleşik yapılara sahip olmadığından programcının çabaları ve işlemlerin kullanılması gerekir.

Globallerin kilit kullanmadan izolasyon seviyesi READ UNCOMMITED olup, kilit kullanıldığında SERIALIZE seviyesine kadar sağlanabilir.

Globallerdeki işlemlerin doğruluğu ve hızı büyük ölçüde programcının becerisine bağlıdır: Okuma sırasında ne kadar yaygın olarak paylaşılan kilitler kullanılırsa, izolasyon düzeyi o kadar yüksek olur ve ne kadar dar kapsamlı özel kilitler alınırsa performans o kadar hızlı olur.

Kaynak: habr.com

Yorum ekle