Transaksi dalam InterSystems IRIS globals

Transaksi dalam InterSystems IRIS globalsInterSystems IRIS DBMS menyokong struktur yang menarik untuk menyimpan data - global. Pada asasnya, ini adalah kunci berbilang peringkat dengan pelbagai barangan tambahan dalam bentuk transaksi, fungsi pantas untuk melintasi pepohon data, kunci dan bahasa ObjectScriptnya sendiri.

Baca lebih lanjut tentang global dalam siri artikel "Global adalah pedang harta karun untuk menyimpan data":

pokok. Bahagian 1
pokok. Bahagian 2
Susunan jarang. Bahagian 3

Saya mula berminat dengan cara urus niaga dilaksanakan di peringkat global, apakah ciri yang ada. Lagipun, ini adalah struktur yang sama sekali berbeza untuk menyimpan data daripada jadual biasa. Tahap yang jauh lebih rendah.

Seperti yang diketahui dari teori pangkalan data hubungan, pelaksanaan transaksi yang baik mesti memenuhi keperluan ASID:

A - Atom (keatoman). Semua perubahan yang dibuat dalam transaksi atau tiada langsung direkodkan.

C - Ketekalan. Selepas transaksi selesai, keadaan logik pangkalan data mestilah konsisten secara dalaman. Dalam banyak cara, keperluan ini melibatkan pengaturcara, tetapi dalam kes pangkalan data SQL ia juga melibatkan kunci asing.

Saya - Asingkan. Urus niaga berjalan selari tidak boleh menjejaskan satu sama lain.

D - Tahan lasak. Selepas berjaya menyelesaikan urus niaga, masalah pada tahap yang lebih rendah (kegagalan kuasa, contohnya) seharusnya tidak menjejaskan data yang diubah oleh transaksi.

Global ialah struktur data bukan perhubungan. Mereka direka bentuk untuk berjalan dengan sangat pantas pada perkakasan yang sangat terhad. Mari kita lihat pelaksanaan transaksi dalam global menggunakan imej pegawai pelabuhan IRIS.

Untuk menyokong transaksi dalam IRIS, arahan berikut digunakan: TSTART, TCOMMIT, TROLLBACK.

1. Atomiti

Cara paling mudah untuk menyemak ialah atomicity. Kami menyemak dari konsol pangkalan data.

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

Kemudian kita membuat kesimpulan:

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

Kita mendapatkan:

1 2 3

Semuanya baik-baik sahaja. Atomiti dikekalkan: semua perubahan direkodkan.

Mari rumitkan tugas, perkenalkan ralat dan lihat cara transaksi disimpan, sebahagian atau tidak sama sekali.

Mari kita semak semula atomicity:

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

Kemudian kami akan menghentikan kontena secara paksa, melancarkannya dan lihat.

docker kill my-iris

Perintah ini hampir bersamaan dengan penutupan paksa, kerana ia menghantar isyarat SIGKILL untuk menghentikan proses serta-merta.

Mungkin urus niaga itu telah disimpan sebahagiannya?

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

- Tidak, ia tidak bertahan.

Mari cuba perintah rollback:

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)

Tiada yang terselamat juga.

2. Konsisten

Memandangkan dalam pangkalan data berdasarkan global, kunci juga dibuat pada global (biar saya ingatkan anda bahawa global ialah struktur peringkat rendah untuk menyimpan data daripada jadual hubungan), untuk memenuhi keperluan ketekalan, perubahan dalam kunci mesti disertakan dalam urus niaga yang sama seperti perubahan dalam global.

Sebagai contoh, kami mempunyai ^orang global, di mana kami menyimpan personaliti dan kami menggunakan TIN sebagai kunci.

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

Untuk mendapatkan carian pantas mengikut nama keluarga dan nama pertama, kami membuat kekunci ^index.

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

Agar pangkalan data menjadi konsisten, kita mesti menambah persona seperti ini:

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

Sehubungan itu, apabila memadam kita juga mesti menggunakan transaksi:

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

Dalam erti kata lain, memenuhi keperluan konsistensi terletak sepenuhnya di bahu pengaturcara. Tetapi apabila ia datang kepada global, ini adalah perkara biasa, kerana sifat peringkat rendah mereka.

3. Pengasingan

Di sinilah hutan bermula. Ramai pengguna secara serentak bekerja pada pangkalan data yang sama, menukar data yang sama.

Keadaan ini adalah setanding apabila ramai pengguna secara serentak bekerja dengan repositori kod yang sama dan cuba melakukan perubahan pada banyak fail secara serentak.

Pangkalan data harus menyusun semuanya dalam masa nyata. Memandangkan dalam syarikat yang serius terdapat orang istimewa yang bertanggungjawab untuk kawalan versi (untuk menggabungkan cawangan, menyelesaikan konflik, dll.), dan pangkalan data mesti melakukan semua ini dalam masa nyata, kerumitan tugas dan ketepatan reka bentuk pangkalan data dan kod yang menyediakannya.

Pangkalan data tidak dapat memahami maksud tindakan yang dilakukan oleh pengguna untuk mengelakkan konflik jika mereka mengusahakan data yang sama. Ia hanya boleh membuat asal satu transaksi yang bercanggah dengan yang lain, atau melaksanakannya secara berurutan.

Masalah lain ialah semasa pelaksanaan transaksi (sebelum komit), keadaan pangkalan data mungkin tidak konsisten, jadi adalah wajar transaksi lain tidak mempunyai akses kepada keadaan pangkalan data yang tidak konsisten, yang dicapai dalam pangkalan data hubungan. dalam banyak cara: mencipta syot kilat, baris berbilang versi dan lain-lain.

Apabila melaksanakan urus niaga secara selari, adalah penting bagi kita bahawa mereka tidak mengganggu satu sama lain. Ini adalah sifat pengasingan.

SQL mentakrifkan 4 tahap pengasingan:

  • BACA TAK KOMITED
  • BACA KOMITED
  • BACA DIULANG
  • BOLEH BERSIRI

Mari lihat setiap peringkat secara berasingan. Kos melaksanakan setiap peringkat meningkat hampir dengan pesat.

BACA TAK KOMITED - ini adalah tahap pengasingan yang paling rendah, tetapi pada masa yang sama yang terpantas. Transaksi boleh membaca perubahan yang dibuat oleh satu sama lain.

BACA KOMITED ialah tahap pengasingan seterusnya, iaitu kompromi. Transaksi tidak boleh membaca perubahan satu sama lain sebelum komit, tetapi mereka boleh membaca sebarang perubahan yang dibuat selepas komit.

Jika kita mempunyai T1 transaksi yang panjang, di mana komit berlaku dalam transaksi T2, T3 ... Tn, yang berfungsi dengan data yang sama seperti T1, maka apabila meminta data dalam T1 kita akan mendapat hasil yang berbeza setiap kali. Fenomena ini dipanggil bacaan tidak berulang.

BACA DIULANG — dalam tahap pengasingan ini kami tidak mempunyai fenomena bacaan tidak boleh berulang, kerana fakta bahawa untuk setiap permintaan untuk membaca data, syot kilat data hasil dibuat dan apabila digunakan semula dalam transaksi yang sama, data daripada syot kilat digunakan. Walau bagaimanapun, adalah mungkin untuk membaca data hantu pada tahap pengasingan ini. Ini merujuk kepada membaca baris baharu yang ditambahkan oleh urus niaga komited selari.

BOLEH BERSIRI - tahap penebat tertinggi. Ia dicirikan oleh fakta bahawa data yang digunakan dalam apa jua cara dalam transaksi (membaca atau menukar) menjadi tersedia untuk transaksi lain hanya selepas selesai transaksi pertama.

Mula-mula, mari kita fikirkan sama ada terdapat pengasingan operasi dalam urus niaga daripada urutan utama. Mari buka 2 tingkap terminal.

Kill ^t

Write ^t(1)
2

TSTART
Set ^t(1)=2

Tiada pengasingan. Satu urutan melihat apa yang dilakukan oleh yang kedua yang membuka transaksi.

Mari lihat sama ada urus niaga bagi urutan yang berbeza melihat apa yang berlaku di dalamnya.

Mari buka 2 tetingkap terminal dan buka 2 transaksi secara selari.

kill ^t
TSTART
Write ^t(1)
3

TSTART
Set ^t(1)=3

Urus niaga selari melihat data antara satu sama lain. Jadi, kami mendapat tahap pengasingan yang paling mudah, tetapi juga terpantas, BACA TANPA KOMITED.

Pada dasarnya, ini boleh dijangkakan untuk global, yang prestasinya sentiasa menjadi keutamaan.

Bagaimana jika kita memerlukan tahap pengasingan yang lebih tinggi dalam operasi di peringkat global?

Di sini anda perlu memikirkan mengapa tahap pengasingan diperlukan sama sekali dan cara ia berfungsi.

Tahap pengasingan tertinggi, SERIALIZE, bermakna hasil transaksi yang dilaksanakan secara selari adalah bersamaan dengan pelaksanaan berurutan mereka, yang menjamin ketiadaan perlanggaran.

Kita boleh melakukan ini menggunakan kunci pintar dalam ObjectScript, yang mempunyai banyak kegunaan berbeza: anda boleh melakukan penguncian biasa, tambahan, berbilang dengan arahan LOCK.

Tahap pengasingan yang lebih rendah adalah pertukaran yang direka untuk meningkatkan kelajuan pangkalan data.

Mari lihat bagaimana kita boleh mencapai tahap pengasingan yang berbeza menggunakan kunci.

Pengendali ini membolehkan anda mengambil bukan sahaja kunci eksklusif yang diperlukan untuk menukar data, tetapi yang dipanggil kunci kongsi, yang boleh mengambil beberapa utas selari apabila mereka perlu membaca data yang tidak sepatutnya diubah oleh proses lain semasa proses membaca.

Maklumat lanjut tentang kaedah penyekatan dua fasa dalam bahasa Rusia dan Inggeris:

Penyekatan dua fasa
Penguncian dua fasa

Kesukarannya ialah semasa transaksi keadaan pangkalan data mungkin tidak konsisten, tetapi data tidak konsisten ini boleh dilihat oleh proses lain. Bagaimana untuk mengelakkan ini?

Menggunakan kunci, kami akan mencipta tetingkap keterlihatan di mana keadaan pangkalan data akan konsisten. Dan semua akses kepada tingkap keterlihatan seperti keadaan yang dipersetujui akan dikawal oleh kunci.

Kunci yang dikongsi pada data yang sama boleh diguna semula—beberapa proses boleh mengambilnya. Kunci ini menghalang proses lain daripada menukar data, i.e. ia digunakan untuk membentuk tingkap keadaan pangkalan data yang konsisten.

Kunci eksklusif digunakan untuk perubahan data - hanya satu proses boleh mengambil kunci sedemikian. Kunci eksklusif boleh diambil dengan:

  1. Sebarang proses jika data adalah percuma
  2. Hanya proses yang mempunyai kunci kongsi pada data ini dan merupakan yang pertama meminta kunci eksklusif.

Transaksi dalam InterSystems IRIS globals

Semakin sempit tetingkap keterlihatan, semakin lama proses lain perlu menunggunya, tetapi semakin konsisten keadaan pangkalan data di dalamnya.

READ_COMMITTED — intipati tahap ini ialah kita hanya melihat data komited daripada rangkaian lain. Jika data dalam transaksi lain masih belum dilakukan, maka kita melihat versi lamanya.

Ini membolehkan kami menyelaraskan kerja dan bukannya menunggu kunci dilepaskan.

Tanpa helah khas, kami tidak akan dapat melihat versi lama data dalam IRIS, jadi kami perlu membuat kaitan dengan kunci.

Sehubungan itu, kami perlu menggunakan kunci kongsi untuk membenarkan data dibaca hanya pada saat-saat konsisten.

Katakan kita mempunyai pangkalan pengguna ^orang yang memindahkan wang kepada satu sama lain.

Detik pemindahan daripada orang 123 kepada orang 242:

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)

Saat meminta jumlah wang daripada orang 123 sebelum mendebit mesti disertakan dengan blok eksklusif (secara lalai):

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

Dan jika anda perlu menunjukkan status akaun dalam akaun peribadi anda, maka anda boleh menggunakan kunci kongsi atau tidak menggunakannya sama sekali:

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

Walau bagaimanapun, jika kita mengandaikan bahawa operasi pangkalan data dilakukan hampir serta-merta (biar saya ingatkan anda bahawa global adalah struktur tahap yang jauh lebih rendah daripada jadual hubungan), maka keperluan untuk tahap ini berkurangan.

BACA DIULANG - Tahap pengasingan ini membenarkan bacaan berbilang data yang boleh diubah suai oleh transaksi serentak.

Sehubungan itu, kami perlu meletakkan kunci kongsi untuk membaca data yang kami ubah dan kunci eksklusif pada data yang kami ubah.

Mujurlah, pengendali LOCK membenarkan anda menyenaraikan secara terperinci semua kunci yang diperlukan, yang mungkin terdapat banyak, dalam satu kenyataan.

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

operasi lain (pada masa ini urutan selari cuba menukar ^orang(123, jumlah), tetapi tidak boleh)

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

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

Apabila menyenaraikan kunci yang dipisahkan dengan koma, kunci tersebut diambil secara berurutan, tetapi jika anda melakukan ini:

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

kemudian mereka diambil secara atom sekali gus.

SERIISKAN — kita perlu menetapkan kunci supaya akhirnya semua transaksi yang mempunyai data biasa dilaksanakan secara berurutan. Untuk pendekatan ini, kebanyakan kunci harus eksklusif dan diambil pada kawasan terkecil di dunia untuk prestasi.

Jika kita bercakap tentang mendebit dana dalam ^orang global, maka hanya tahap pengasingan SERIALIZE sahaja yang boleh diterima untuknya, kerana wang mesti dibelanjakan dengan ketat mengikut urutan, jika tidak, jumlah yang sama boleh dibelanjakan beberapa kali.

4. Ketahanan

Saya menjalankan ujian dengan pemotongan keras bekas menggunakan

docker kill my-iris

Pangkalan itu bertolak ansur dengan mereka dengan baik. Tiada masalah dikenalpasti.

Kesimpulan

Untuk global, InterSystems IRIS mempunyai sokongan transaksi. Mereka benar-benar atom dan boleh dipercayai. Untuk memastikan ketekalan pangkalan data berdasarkan global, usaha pengaturcara dan penggunaan transaksi diperlukan, kerana ia tidak mempunyai binaan terbina dalam yang kompleks seperti kunci asing.

Tahap pengasingan global tanpa menggunakan kunci adalah READ UNCOMMITED, dan apabila menggunakan kunci ia boleh dipastikan sehingga tahap SERIALIZE.

Ketepatan dan kelajuan urus niaga di peringkat global sangat bergantung pada kemahiran pengaturcara: semakin banyak kunci yang dikongsi digunakan semasa membaca, semakin tinggi tahap pengasingan, dan semakin sempit kunci eksklusif diambil, semakin cepat prestasinya.

Sumber: www.habr.com

Tambah komen