Teks decoding logis dari komit dua fase di PostgreSQL 14

Pembaruan: 2 Juli 2023

Teks decoding logis dari komit dua fase di PostgreSQL 14

Tim OSS Fujitsu dan komunitas open source PostgreSQL telah bekerja sama untuk menambahkan fungsi dekripsi komit dua fase dalam replikasi logis di PG14. Mari kita lihat apa saja fitur ini?

latar belakang

Komitmen dua fase adalah mekanisme di mana transaksi dilakukan dalam dua fase. Biasanya digunakan dalam database terdistribusi untuk memastikan konsistensi. Dua fase transaksi adalah fase PERSIAPAN dan fase COMMIT/ROLLBACK. Perintah yang disampaikan dalam dua fase di PG adalah:

SIAPKAN TRANSAKSI

PERSIAPAN KOMITMEN

ROLLBACK DIPERSIAPKAN

PG sudah mendukung komit dua fase di versi 8.0, dan versi 10.0 mendukung replikasi logis. Namun, komit dua fase tidak pernah didukung dalam replikasi logis. Perintah PREPARE TRANSACTION, COMMIT PREPARED, dan ROLLBACK PREPARED telah didukung dalam satu contoh, tetapi ketika perintah ini perlu disalin secara logis ke mesin siaga, perintah tersebut tidak lagi mempertahankan arti aslinya. Perintah PREPARE TRANSACTION diperlakukan sebagai NOP dan tidak diterjemahkan sama sekali. Perintah COMMIT PREPARED dianggap sebagai COMMIT, dan perintah ROLLBACK PREPARED dianggap sebagai ABORT.

Apa itu komit dua fase?

Komit dua fase adalah protokol komit atom yang membantu menjaga konsistensi antara database terdistribusi. Komit biasa yang menyediakan atomisitas dalam database tidak cukup untuk memberikan konsistensi untuk transaksi lintas database. Untuk mengilustrasikan masalah ini, mari kita berikan sebuah contoh:

1) John memiliki 300$ di Bank A

2) Mark memiliki 100$ di Bank B

3) John ingin mentransfer $100 ke Mark

Selama transaksi, Anda perlu menarik 100$ dari Bank A ke Bank B. Di akhir transaksi, harus ada 200$. Jika ada transaksi yang gagal setiap saat selama proses transfer, status akun harus dikembalikan ke keadaan sebelum transfer dimulai. Transaksi mungkin gagal karena berbagai alasan. Jika terjadi gangguan sebelum transaksi dilakukan, transaksi akan dibatalkan. Dalam contoh kita, jika interupsi terjadi ketika akun John dikurangi, maka akun John dari port interupsi tidak boleh dikurangi. Beginilah cara komit sederhana menjaga konsistensi dalam database.

Tetapi kami mempertimbangkan situasi seperti itu, yaitu, transaksi yang mengurangi $100 dari rekening John berhasil dalam satu kali pengajuan, tetapi transaksi yang menambahkan $100 ke rekening Mark di Bank B gagal dan dibatalkan. Setelah operasi ini selesai, meskipun rekening John telah didebet, Mark tidak akan menerima jumlahnya. 100$ menghilang. Saat berurusan dengan transaksi terdistribusi, komit sederhana mungkin gagal.

Eksekusi langkah demi langkah dari transaksi terdistribusi

Untuk komit dua fase, salah satu database bertindak sebagai koordinator transaksi terdistribusi.

Tahap 1

Sebuah database mulai menerapkan transaksi, dan kemudian mempersiapkan. Ini mengirimkan transaksi yang disiapkan ke database lain dalam bentuk pesan persiapan. Basis data kedua mendapatkan pesan Siapkan, lalu siapkan transaksi. Siapkan melibatkan perubahan dalam transaksi, tetapi tidak melakukan. Data kotor ditulis ke disk untuk kegigihan. Setelah semua database menyiapkan transaksi, dan semua informasi tentang transaksi disimpan di disk, fase persiapan selesai.

Tahap 2

Selanjutnya, arbiter memulai fase commit. Jika database kedua gagal menyiapkan transaksi karena alasan tertentu, arbiter memulai fase rollback. Oleh karena itu, tergantung pada apakah persiapan berhasil, transaksi akan dilakukan atau dibatalkan. Interupsi pada fase komit terakhir dapat dipulihkan, karena transaksi persiapan yang diperlukan telah ditulis ke disk dan dapat diterapkan kembali.

Komit dua fase tidak terkait dengan database instance tunggal, tetapi relevan ketika data direplikasi di beberapa instance database.

Sangat penting untuk mendukung komit dua fase dalam replikasi logis.

Gambaran Fungsional

Sebelum versi PG14, transaksi replikasi logis didekodekan dan direplikasi hanya setelah transaksi dilakukan. Hal ini untuk menghindari bahwa transaksi replikasi pada akhirnya dapat dibatalkan.

Decode transaksi pada komit

Replikasi logis PG14 mendukung perintah PREPARE TRANSACTION, COMMIT PREPARED dan ROOLBACK PREPARED. Ketika perintah PREPARE TRANSACTION didekode, transaksi didekode dan disalin. SIAPKAN TRANSAKSI memulai replay dan decoding transaksi seperti COMMIT di WAL SENDER.

Decoding transaksi selama persiapan

Kami juga menetapkan panggilan balik plug-in baru untuk memungkinkan plug-in decoding logis untuk mendukung pengiriman dua fase.

Callback

menggambarkan

filter_persiapkan_cb

Izinkan plugin untuk memfilter transaksi yang tidak perlu didekodekan saat menyiapkan sesuai dengan GID yang digunakan dalam perintah SIAPKAN TRANSAKSI

mulai_persiapkan_cb

Mulai dari Siapkan transaksi

mempersiapkan_cb

Dipanggil ketika perintah SIAPKAN TRANSAKSI diterjemahkan

komit_siapcb

Dipanggil ketika perintah COMMIT PREPARED diterjemahkan

kembalikan_siapcb

Dipanggil saat perintah ROLLBACK PREPARED diterjemahkan

Modifikasi plug-in

tes_dekode

Plug-in adalah plug-in output decoding logis, sebagai contoh untuk membantu pengguna mengembangkan plug-in decoding logis mereka sendiri. test_decoding menerima WAL melalui mekanisme decoding logis dan menerjemahkannya menjadi representasi tekstual dari operasi yang dilakukan.

Ini telah dimodifikasi untuk dapat menggunakan fungsi panggilan balik dua tahap baru dan transaksi dekode selama persiapan

Modifikasi API

pg_buatlogis_replikasi_slot()

API menambahkan opsi baru untuk menentukan apakah slot mendukung komit dua fase. Plugin keluaran dapat menggunakan slot replikasi dengan opsi dua fase untuk mendukung komit dua fase.

pg_buat_logis_replikasi_slot(slot_nama nama,nama plugin boolean sementara,boolean dua_fase

Studi kasus

Mari kita lihat cara mendeteksi output yang didekodekan dari transaksi komit dua fase:

1) Buat slot replikasi

Gunakan test_decoding sebagai plug-in output, dan berikan true sehingga slot mendukung pengiriman dan decoding dua tahap.

postgres=# SELECT FROM pg_create_logical_replication_slot('regressionslot', test_decoding', false, true);

slot_nama lsn

kan

regresi_slot 0/16B1970

1 baris)

2) Buat tabel

postgres CREATE TABLE data id kunci primer serial teks data

BUAT TABEL

3) Mendeteksi konten keluaran yang didekodekan dari transaksi persiapan dan transaksi komit

postgres=# MULAI;

postgres=*# MASUKKAN KE data(data) NILAI('5');

postgres=*# SIAPKAN TRANSAKSI tes_siap1';

postgres=# SELECT FROM pg_logical_slot_get_changesregressionslot', NULL, NULL);

lsn xid data

kan

0/1689DC0 529 MULAI 529

0/1689DC0 529 tabel publik.data: INSERT: id[integer]:3 data[teks]:'5'

0/1689FC0 529 SIAPKAN TRANSAKSI tes_siap1', txid 529

3 baris)

postgres=# COMMIT PREPARED test_prepared1';

postgres=# pilih dari pg_logical_slot_get_changesregressionslot', NULL, NULL);

lsn xid data

kan

0/168A060 529 COMMIT PREPARED test_prepared1', txid 529

4 baris)

postgres=# pilih dari data;

id data

kan

1 5

1 baris)

masa depan

Perubahan PG14 ke fungsi ini memiliki infrastruktur sisi dekoder yang memungkinkan pengiriman dekode dua tahap selama persiapan. Kami juga memodifikasi plugin test_decoding untuk memanfaatkan infrastruktur ini.

Langkah selanjutnya adalah menerapkan dukungan dua tahap ke plug-in decoding logis terbesar di PG-plug-in pgoutput. Plug-in ini mendukung mode replikasi logis PUBLISHER/SUBSCRIBER. Ini adalah plug-in yang paling banyak digunakan dalam replikasi logis. Tim OSS Fujitsu bekerja sama dengan komunitas open source untuk menambahkan fitur ini ke PG15.

Untuk transaksi dua fase dalam database terdistribusi, PG juga perlu mendukung: mesin siaga menginformasikan host bahwa PREPARE telah gagal dan memulai rollback. Mekanisme umpan balik ini tidak didukung di PG dan merupakan salah satu arah untuk perbaikan di masa depan.

  Link:

6mbi25l-120

rm500uz-2j