MariaDB
 sql >> Teknologi Basis Data >  >> RDS >> MariaDB

Menangani Masalah Replikasi dari Cluster Database MariaDB non-GTID ke GTID

Kami baru-baru ini mengalami kasus dukungan pelanggan yang menarik yang melibatkan penyiapan replikasi MariaDB. Kami menghabiskan banyak waktu untuk meneliti masalah ini dan berpikir akan bermanfaat untuk membagikannya kepada Anda di entri blog ini.

Deskripsi Lingkungan Pelanggan

Masalahnya adalah sebagai berikut:server MariaDB lama (sebelum 10.x) sedang digunakan dan upaya telah dilakukan untuk memigrasikan data dari server tersebut ke penyiapan replikasi MariaDB yang lebih baru. Hal ini mengakibatkan masalah dengan menggunakan Mariabackup untuk membangun kembali budak di cluster replikasi baru. Untuk tujuan pengujian, kami membuat ulang perilaku ini di lingkungan berikut:

Data telah dipindahkan dari 5,5 ke 10,4 menggunakan mysqldump:

mysqldump --single-transaction --master-data=2 --events --routines sbtest > /root/dump.sql

Ini memungkinkan kami mengumpulkan koordinat log biner master dan dump yang konsisten. Hasilnya, kami dapat menyediakan node master MariaDB 10.4 dan mengatur replikasi antara master 5.5 lama dan node 10.4 baru. Lalu lintas masih berjalan di 5,5 node. 10.4 master menghasilkan GTID karena harus mereplikasi data ke 10.4 slave. Sebelum kita menggali lebih dalam, mari kita lihat sekilas cara kerja GTID di MariaDB.

MariaDB dan GTID

Sebagai permulaan, MariaDB menggunakan format GTID yang berbeda dari Oracle MySQL. Ini terdiri dari tiga angka yang dipisahkan oleh tanda hubung:

0 - 1 - 345

Pertama adalah domain replikasi, yang memungkinkan replikasi multi-sumber ditangani dengan benar. Ini tidak relevan dengan kasus kami karena semua node berada dalam domain replikasi yang sama. Nomor kedua adalah ID server dari node yang menghasilkan GTID. Yang ketiga adalah nomor urut - secara monoton meningkat dengan setiap peristiwa yang disimpan dalam log biner.

MariaDB menggunakan beberapa variabel untuk menyimpan informasi tentang GTID yang dijalankan pada node tertentu. Yang paling menarik bagi kami adalah:

Gtid_binlog_pos - sesuai dokumentasi, variabel ini adalah GTID dari grup peristiwa terakhir yang ditulis ke log biner.

Gtid_slave_pos - sesuai dokumentasi, variabel sistem ini berisi GTID dari transaksi terakhir yang diterapkan ke database oleh utas budak server.

Gtid_current_pos - sesuai dokumentasi, variabel sistem ini berisi GTID dari transaksi terakhir yang diterapkan ke database. Jika server_id dari GTID yang sesuai di gtid_binlog_pos sama dengan server_id milik server, dan nomor urut lebih tinggi dari GTID yang sesuai di gtid_slave_pos, maka GTID dari gtid_binlog_pos akan digunakan. Jika tidak, GTID dari gtid_slave_pos akan digunakan untuk domain tersebut.

Jadi, untuk memperjelas, gtid_binlog_pos menyimpan GTID dari acara yang terakhir dieksekusi secara lokal. Gtid_slave_pos menyimpan GTID dari acara yang dieksekusi oleh utas budak dan gtid_current_pos menunjukkan nilai dari gtid_binlog_pos, jika memiliki nomor urut tertinggi dan memiliki server-id atau gtid_slave_pos jika memiliki urutan tertinggi. Harap ingat ini.

Ikhtisar Masalah

Status awal variabel yang relevan ada di 10.4 master:

MariaDB [(none)]> show global variables like '%gtid%';

+-------------------------+----------+

| Variable_name           | Value |

+-------------------------+----------+

| gtid_binlog_pos         | 0-1001-1 |

| gtid_binlog_state       | 0-1001-1 |

| gtid_cleanup_batch_size | 64       |

| gtid_current_pos        | 0-1001-1 |

| gtid_domain_id          | 0 |

| gtid_ignore_duplicates  | ON |

| gtid_pos_auto_engines   | |

| gtid_slave_pos          | 0-1001-1 |

| gtid_strict_mode        | ON |

| wsrep_gtid_domain_id    | 0 |

| wsrep_gtid_mode         | OFF |

+-------------------------+----------+

11 rows in set (0.001 sec)

Harap perhatikan gtid_slave_pos yang, secara teoritis, tidak masuk akal - itu berasal dari node yang sama tetapi melalui utas budak. Ini bisa terjadi jika Anda membuat saklar utama sebelumnya. Kami melakukannya - dengan dua node 10,4 kami mengganti master dari host dengan ID server 1001 ke host dengan ID server 1002 dan kemudian kembali ke 1001.

Setelah itu kami mengonfigurasi replikasi dari 5,5 hingga 10,4 dan seperti inilah tampilannya:

MariaDB [(none)]> show global variables like '%gtid%';

+-------------------------+-------------------------+

| Variable_name           | Value |

+-------------------------+-------------------------+

| gtid_binlog_pos         | 0-55-117029 |

| gtid_binlog_state       | 0-1001-1537,0-55-117029 |

| gtid_cleanup_batch_size | 64                      |

| gtid_current_pos        | 0-1001-1 |

| gtid_domain_id          | 0 |

| gtid_ignore_duplicates  | ON |

| gtid_pos_auto_engines   | |

| gtid_slave_pos          | 0-1001-1 |

| gtid_strict_mode        | ON |

| wsrep_gtid_domain_id    | 0 |

| wsrep_gtid_mode         | OFF |

+-------------------------+-------------------------+

11 rows in set (0.000 sec)

Seperti yang Anda lihat, peristiwa yang direplikasi dari MariaDB 5.5, semuanya telah diperhitungkan dalam variabel gtid_binlog_pos:semua peristiwa dengan ID server 55. Ini menghasilkan masalah serius. Seperti yang mungkin Anda ingat, gtid_binlog_pos harus berisi acara yang dieksekusi secara lokal di host. Ini berisi peristiwa yang direplikasi dari server lain dengan ID server yang berbeda.

Ini membuat segalanya tidak pasti ketika Anda ingin membangun kembali budak 10.4, inilah alasannya. Mariabackup, sama seperti Xtrabackup, bekerja dengan cara yang sederhana. Ini menyalin file dari server MariaDB saat memindai redo log dan menyimpan transaksi masuk apa pun. Ketika file telah disalin, Mariabackup akan membekukan database menggunakan FLUSH TABLES WITH READ LOCK atau kunci cadangan, tergantung pada versi MariaDB dan ketersediaan kunci cadangan. Kemudian ia membaca GTID terbaru yang dieksekusi dan menyimpannya di samping cadangan. Kemudian kunci dilepaskan dan pencadangan selesai. GTID yang disimpan dalam cadangan harus digunakan sebagai GTID terbaru yang dieksekusi pada sebuah node. Dalam kasus membangun kembali budak itu akan ditempatkan sebagai gtid_slave_pos dan kemudian digunakan untuk memulai replikasi GTID. GTID ini diambil dari gtid_current_pos, yang sangat masuk akal - bagaimanapun juga, ini adalah “GTID dari transaksi terakhir yang diterapkan ke database”. Pembaca yang akut sudah bisa melihat masalahnya. Mari kita tunjukkan output dari variabel ketika 10.4 direplikasi dari master 5.5:

MariaDB [(none)]> show global variables like '%gtid%';

+-------------------------+-------------------------+

| Variable_name           | Value |

+-------------------------+-------------------------+

| gtid_binlog_pos         | 0-55-117029 |

| gtid_binlog_state       | 0-1001-1537,0-55-117029 |

| gtid_cleanup_batch_size | 64                      |

| gtid_current_pos        | 0-1001-1 |

| gtid_domain_id          | 0 |

| gtid_ignore_duplicates  | ON |

| gtid_pos_auto_engines   | |

| gtid_slave_pos          | 0-1001-1 |

| gtid_strict_mode        | ON |

| wsrep_gtid_domain_id    | 0 |

| wsrep_gtid_mode         | OFF |

+-------------------------+-------------------------+

11 rows in set (0.000 sec)

Gtid_current_pos disetel ke 0-1001-1. Ini jelas bukan momen yang tepat, ini diambil dari gtid_slave_pos sementara kami memiliki banyak transaksi yang berasal dari 5,5 setelah itu. Masalahnya adalah bahwa transaksi tersebut disimpan sebagai gtid_binlog_pos. Di sisi lain gtid_current_pos dihitung sedemikian rupa sehingga memerlukan ID server lokal untuk GTID di gitd_binlog_pos sebelum dapat digunakan sebagai gtid_current_pos. Dalam kasus kami, mereka memiliki ID server dari node 5.5 sehingga mereka tidak akan diperlakukan dengan benar sebagai peristiwa yang dijalankan pada master 10.4. Setelah pemulihan cadangan, jika Anda mengatur budak sesuai dengan status GTID yang disimpan dalam cadangan, itu akan berakhir dengan menerapkan kembali semua peristiwa yang berasal dari 5.5. Ini, jelas, akan mematahkan replikasi.

Solusi

Solusi untuk masalah ini adalah dengan mengambil beberapa langkah tambahan:

  1. Hentikan replikasi dari 5,5 hingga 10,4. Jalankan STOP SLAVE di master 10.4
  2. Jalankan transaksi apa pun pada 10.4 - BUAT SKEMA JIKA TIDAK ADA perbaikan bug - ini akan mengubah situasi GTID seperti ini:
MariaDB [(none)]> show global variables like '%gtid%';

+-------------------------+---------------------------+

| Variable_name           | Value   |

+-------------------------+---------------------------+

| gtid_binlog_pos         | 0-1001-117122   |

| gtid_binlog_state       | 0-55-117121,0-1001-117122 |

| gtid_cleanup_batch_size | 64                        |

| gtid_current_pos        | 0-1001-117122   |

| gtid_domain_id          | 0   |

| gtid_ignore_duplicates  | ON   |

| gtid_pos_auto_engines   |   |

| gtid_slave_pos          | 0-1001-1   |

| gtid_strict_mode        | ON   |

| wsrep_gtid_domain_id    | 0   |

| wsrep_gtid_mode         | OFF   |

+-------------------------+---------------------------+

11 rows in set (0.001 sec)

GITD terbaru dijalankan secara lokal, jadi disimpan sebagai gtid_binlog_pos. Karena memiliki ID server lokal, ia dipilih sebagai gtid_current_pos. Sekarang, Anda dapat mengambil cadangan dan menggunakannya untuk membangun kembali budak dari 10.4 master. Setelah ini selesai, mulai utas budak lagi.

MariaDB mengetahui bahwa jenis bug ini ada, salah satu laporan bug relevan yang kami temukan adalah: https://jira.mariadb.org/browse/MDEV-10279 Sayangnya, sejauh ini belum ada perbaikan . Apa yang kami temukan adalah bahwa masalah ini memengaruhi MariaDB hingga 5.5. Peristiwa non-GTID yang berasal dari MariaDB 10.0 diperhitungkan dengan benar pada 10.4 sebagai berasal dari utas budak dan gtid_slave_pos diperbarui dengan benar. MariaDB 5.5 cukup lama (meskipun masih didukung) sehingga Anda masih dapat melihat pengaturan yang berjalan di dalamnya dan mencoba untuk bermigrasi dari versi 5.5 ke versi MariaDB yang mendukung GTID. Yang lebih parah, menurut laporan bug yang kami temukan, ini juga memengaruhi replikasi yang berasal dari server non-MariaDB (salah satu komentar menyebutkan masalah yang muncul di Percona Server 5.6) ke dalam MariaDB.

Bagaimanapun, kami harap postingan blog ini bermanfaat bagi Anda dan semoga Anda tidak mengalami masalah yang baru saja kami jelaskan.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. COUNT() Fungsi di MariaDB

  2. Melambung lebih tinggi di cloud dengan MariaDB SkySQL

  3. Menggunakan Replikasi Cluster Galera MySQL untuk Membuat Cluster Geo-Distributed:Bagian Satu

  4. Setel Kumpulan Karakter dan Pengumpulan Database di MariaDB

  5. 7 Cara Mengembalikan Baris Duplikat yang memiliki Kunci Utama di MariaDB