Replikasi bukan cadangan. Atau tidak? Inilah cara kami menggunakan replikasi yang ditangguhkan untuk memulihkan pintasan yang terhapus secara tidak sengaja.
Replikasi bukan merupakan sarana untuk membuat cadangan database (gitlab-ce
Dengan replika yang ditangguhkan, kami memulihkan data hanya dalam 1,5 jam. Lihat bagaimana hal itu terjadi.
Pemulihan titik waktu dengan PostgreSQL
PostgreSQL memiliki fungsi bawaan yang memulihkan keadaan database ke titik waktu tertentu. Itu disebut
Untuk menggunakan fitur ini untuk pencadangan dingin, kami secara rutin membuat pencadangan basis data dasar dan menyimpannya dalam arsip (arsip GitLab ada di
Apa itu replikasi yang ditangguhkan?
Replikasi malas adalah penerapan perubahan dari WAL dengan penundaan. Artinya, transaksi terjadi dalam satu jam X
, namun akan muncul di replika dengan penundaan d
dalam jam X + d
.
PostgreSQL memiliki 2 cara untuk menyiapkan replika database fisik: pemulihan cadangan dan replikasi streaming.
Cara mengatur pemulihan tertunda dari arsip
recovery.conf
. Contoh:
standby_mode = 'on'
restore_command = '/usr/bin/envdir /etc/wal-e.d/env /opt/wal-e/bin/wal-e wal-fetch -p 4 "%f" "%p"'
recovery_min_apply_delay = '8h'
recovery_target_timeline = 'latest'
Dengan parameter ini, kami mengonfigurasi replika yang ditangguhkan dengan pemulihan cadangan. Di sini digunakan restore_command
) dari arsip, dan perubahan akan diterapkan setelah delapan jam (recovery_min_apply_delay
). Replika akan mengamati perubahan garis waktu dalam arsip, misalnya karena kegagalan klaster (recovery_target_timeline
).
Π‘ recovery_min_apply_delay
Anda dapat mengatur replikasi streaming dengan penundaan, namun ada beberapa kendala di sini yang terkait dengan slot replikasi, umpan balik siaga panas, dan sebagainya. Arsip WAL memungkinkan Anda menghindarinya.
Parameter recovery_min_apply_delay
hanya muncul di PostgreSQL 9.3. Di versi sebelumnya, untuk replikasi yang ditangguhkan, Anda perlu mengonfigurasi kombinasinya pg_xlog_replay_pause(), pg_xlog_replay_resume()
) atau simpan segmen WAL di arsip selama penundaan.
Bagaimana PostgreSQL melakukan ini?
Sangat menarik untuk melihat bagaimana PostgreSQL mengimplementasikan pemulihan yang lambat. Mari lihat recoveryApplyDelay(XlogReaderState)
static bool
recoveryApplyDelay(XLogReaderState *record)
{
uint8 xact_info;
TimestampTz xtime;
long secs;
int microsecs;
/* nothing to do if no delay configured */
if (recovery_min_apply_delay <= 0)
return false;
/* no delay is applied on a database not yet consistent */
if (!reachedConsistency)
return false;
/*
* Is it a COMMIT record?
*
* We deliberately choose not to delay aborts since they have no effect on
* MVCC. We already allow replay of records that don't have a timestamp,
* so there is already opportunity for issues caused by early conflicts on
* standbys.
*/
if (XLogRecGetRmid(record) != RM_XACT_ID)
return false;
xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
if (xact_info != XLOG_XACT_COMMIT &&
xact_info != XLOG_XACT_COMMIT_PREPARED)
return false;
if (!getRecordTimestamp(record, &xtime))
return false;
recoveryDelayUntilTime =
TimestampTzPlusMilliseconds(xtime, recovery_min_apply_delay);
/*
* Exit without arming the latch if it's already past time to apply this
* record
*/
TimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime,
&secs, µsecs);
if (secs <= 0 && microsecs <= 0)
return false;
while (true)
{
// Shortened:
// Use WaitLatch until we reached recoveryDelayUntilTime
// and then
break;
}
return true;
}
Intinya adalah penundaan didasarkan pada waktu fisik yang tercatat dalam stempel waktu penerapan transaksi (xtime
). Seperti yang Anda lihat, penundaan hanya berlaku untuk penerapan dan tidak memengaruhi entri lain - semua perubahan diterapkan secara langsung, dan penerapan tertunda, jadi kami hanya akan melihat perubahan setelah penundaan yang dikonfigurasi.
Cara menggunakan replika tertunda untuk memulihkan data
Katakanlah kita memiliki cluster database dan replika dengan penundaan produksi delapan jam. Mari kita lihat cara memulihkan data menggunakan sebuah contoh
Ketika kami mengetahui masalahnya, kami
SELECT pg_xlog_replay_pause();
Dengan jeda, kami tidak memiliki risiko replika tersebut akan mengulangi permintaan tersebut DELETE
. Suatu hal yang berguna jika Anda perlu waktu untuk memikirkan semuanya.
Intinya replika yang ditangguhkan harus mencapai momen sebelum permintaan DELETE
. Kami kira-kira mengetahui waktu fisik pemindahan. Kami telah menghapus recovery_min_apply_delay
dan menambahkan recovery_target_time
Π² recovery.conf
. Beginilah cara replika mencapai momen yang tepat tanpa penundaan:
recovery_target_time = '2018-10-12 09:25:00+00'
Dengan stempel waktu, lebih baik kurangi kelebihannya agar tidak ketinggalan. Benar, semakin besar penurunannya, semakin banyak data yang hilang. Sekali lagi, jika kita melewatkan permintaan tersebut DELETE
, semuanya akan dihapus lagi dan Anda harus memulai dari awal (atau bahkan mengambil cadangan dingin untuk PITR).
Kami memulai kembali instance Postgres yang ditangguhkan dan segmen WAL diulang hingga waktu yang ditentukan. Anda dapat melacak kemajuan pada tahap ini dengan menanyakan:
SELECT
-- current location in WAL
pg_last_xlog_replay_location(),
-- current transaction timestamp (state of the replica)
pg_last_xact_replay_timestamp(),
-- current physical time
now(),
-- the amount of time still to be applied until recovery_target_time has been reached
'2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;
Jika stempel waktu tidak lagi berubah, pemulihan selesai. Tindakan dapat disesuaikan recovery_target_action
Basis data kembali ke keadaannya sebelum permintaan malang itu. Sekarang Anda dapat, misalnya, mengekspor data. Kami mengekspor data label yang dihapus dan semua tautan ke masalah serta permintaan penggabungan dan memindahkannya ke database produksi. Jika kerugiannya besar, Anda cukup mempromosikan replikanya dan menggunakannya sebagai replika utama. Tapi kemudian semua perubahan setelah kita pulih akan hilang.
Daripada stempel waktu, lebih baik menggunakan ID transaksi. Hal ini berguna untuk mencatat ID ini, misalnya, untuk pernyataan DDL (seperti DROP TABLE
), dengan menggunakan log_statements = 'ddl'
. Jika kami memiliki ID transaksi, kami akan mengambil recovery_target_xid
dan menjalankan semuanya hingga transaksi sebelum permintaan DELETE
.
Kembali bekerja sangat sederhana: hapus semua perubahan dari recovery.conf
dan mulai ulang Postgres. Replika ini akan segera mengalami penundaan delapan jam lagi, dan kami siap menghadapi masalah di masa depan.
Manfaat Pemulihan
Dengan replika yang ditangguhkan dan bukan cadangan dingin, Anda tidak perlu menghabiskan waktu berjam-jam memulihkan seluruh gambar dari arsip. Misalnya, kami memerlukan waktu lima jam untuk mendapatkan seluruh cadangan dasar sebesar 2 TB. Dan kemudian Anda masih harus menerapkan seluruh WAL harian untuk pulih ke kondisi yang diinginkan (dalam kasus terburuk).
Replika yang ditangguhkan lebih baik daripada cadangan dingin dalam dua hal:
- Tidak perlu menghapus seluruh cadangan dasar dari arsip.
- Ada jangka waktu tetap delapan jam untuk segmen WAL yang harus diulang.
Kami juga terus-menerus memeriksa apakah mungkin membuat PITR dari WAL, dan kami akan segera mengetahui adanya kerusakan atau masalah lain pada arsip WAL dengan memantau kelambatan replika yang ditangguhkan.
Dalam contoh ini, kami membutuhkan waktu 50 menit untuk memulihkan, artinya kecepatan data WAL adalah 110 GB per jam (arsip masih aktif
Hasil: di mana replika yang ditangguhkan berguna (dan di mana tidak)
Gunakan replikasi tertunda sebagai pertolongan pertama jika Anda kehilangan data secara tidak sengaja dan melihat masalah ini dalam penundaan yang dikonfigurasi.
Namun perlu diingat: replikasi bukanlah cadangan.
Pencadangan dan replikasi memiliki tujuan berbeda. Cadangan dingin akan berguna jika Anda tidak sengaja membuatnya DELETE
ΠΈΠ»ΠΈ DROP TABLE
. Kami membuat cadangan dari cold storage dan memulihkan keadaan tabel atau seluruh database sebelumnya. Tapi sekaligus permintaan DROP TABLE
hampir seketika direproduksi di semua replika pada cluster yang berfungsi, jadi replikasi biasa tidak akan membantu di sini. Replikasi itu sendiri membuat database tetap tersedia ketika masing-masing server disewakan dan mendistribusikan beban.
Bahkan dengan replika yang ditangguhkan, terkadang kita sangat membutuhkan cold backup di tempat yang aman jika terjadi kegagalan pusat data, kerusakan tersembunyi, atau kejadian lain yang tidak segera terlihat. Replikasi saja tidak ada gunanya di sini.
Catatan. Pada
Sumber: www.habr.com