Replication یک نسخه پشتیبان نیست. یا نه؟ در اینجا نحوه استفاده از Lazy Replication برای بازیابی با حذف تصادفی میانبرها آمده است.
Replication ابزار پشتیبان گیری از پایگاه داده شما نیست (gitlab-ce
با کپی تاخیری، ما اطلاعات را تنها در 1,5 ساعت بازیابی کردیم. ببین چطور بود
بازیابی به موقع با PostgreSQL
PostgreSQL دارای یک تابع داخلی است که وضعیت پایگاه داده را به یک نقطه زمانی خاص بازیابی می کند. نامیده می شود
برای استفاده از این ویژگی برای پشتیبان گیری سرد، ما به طور منظم یک نسخه پشتیبان از پایگاه داده پایه تهیه می کنیم و آن را در یک آرشیو ذخیره می کنیم (بایگانی های GitLab در
تکثیر تاخیری چیست؟
تکرار تاخیری اعمال تغییرات از WAL با تاخیر است. یعنی معامله در ساعت اتفاق افتاده است X
، اما با تاخیر در ماکت ظاهر می شود d
در ساعت X + d
.
2 راه برای راه اندازی یک ماکت پایگاه داده فیزیکی در PostgreSQL وجود دارد: بازیابی بایگانی و تکرار جریان.
نحوه تنظیم بازیابی پشتیبان با تاخیر
recovery.conf
... مثال:
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'
با این تنظیمات، ما یک replica تاخیری را با بازیابی بایگانی پیکربندی کرده ایم. در اینجا استفاده شده است restore_command
) از آرشیو، و تغییرات پس از هشت ساعت اعمال می شود (recovery_min_apply_delay
). Replica تغییرات جدول زمانی را در بایگانی مشاهده میکند، مثلاً به دلیل خرابی خوشه (recovery_target_timeline
).
С recovery_min_apply_delay
میتوانید تکرار جریان تأخیر را راهاندازی کنید، اما چند مشکل مرتبط با اسلاتهای تکرار، بازخورد یدکی داغ و غیره وجود دارد. آرشیو WAL از آنها اجتناب می کند.
پارامتر recovery_min_apply_delay
فقط در PostgreSQL 9.3 ظاهر شد. در نسخه های قبلی، تکرار تاخیری نیاز به ترکیبی از pg_xlog_replay_pause(), pg_xlog_replay_resume()
) یا بخش های WAL را در بایگانی برای مدت زمان تاخیر نگه دارید.
PostgreSQL چگونه این کار را انجام می دهد؟
جالب است ببینید PostgreSQL چگونه بازیابی تنبل را پیاده سازی می کند. بیایید نگاهی بیندازیم به 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;
}
نکته اصلی این است که تاخیر بر اساس زمان فیزیکی ثبت شده در مهر زمانی تعهد تراکنش است (xtime
). همانطور که می بینید، تاخیر فقط برای commit ها اعمال می شود و روی رکوردهای دیگر تأثیر نمی گذارد - همه تغییرات به طور مستقیم اعمال می شوند و commit با تاخیر انجام می شود، بنابراین ما تغییرات را تنها پس از تاخیر پیکربندی شده مشاهده خواهیم کرد.
نحوه استفاده از ماکت تنبل برای بازیابی اطلاعات
فرض کنید یک خوشه پایگاه داده در حال تولید و یک ماکت با تاخیر هشت ساعته داریم. بیایید نحوه بازیابی اطلاعات را با استفاده از یک مثال ببینیم
وقتی متوجه مشکل شدیم، ما
SELECT pg_xlog_replay_pause();
با یک مکث، ما هیچ خطری نداشتیم که ماکت درخواست را تکرار کند DELETE
. اگر برای فهمیدن همه چیز به زمان نیاز دارید، چیز مفیدی است.
نکته اصلی این است که ماکت تاخیری باید به لحظه قبل از درخواست برسد DELETE
. ما تقریباً زمان فیزیکی حذف را می دانستیم. حذف کردیم recovery_min_apply_delay
و اضافه کرد recovery_target_time
в recovery.conf
. بنابراین ماکت بدون تاخیر به لحظه مناسب می رسد:
recovery_target_time = '2018-10-12 09:25:00+00'
با مهر زمانی، بهتر است مقدار اضافی را کاهش دهید تا از دست ندهید. درست است، هر چه این کاهش بیشتر باشد، داده های بیشتری را از دست می دهیم. باز هم اگر از درخواست بگذریم DELETE
، همه چیز دوباره حذف می شود و شما باید از نو شروع کنید (یا حتی یک نسخه پشتیبان سرد برای PITR بگیرید).
نمونه تاخیری Postgres را دوباره راه اندازی کردیم و بخش های WAL تا زمان مشخص شده تکرار شدند. شما می توانید پیشرفت را در این مرحله با پرس و جو پیگیری کنید:
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;
اگر مهر زمانی دیگر تغییر نکند، بازیابی کامل شده است. می توانید عمل را سفارشی کنید recovery_target_action
پایگاه داده قبل از آن درخواست بد به این ایالت آمد. اکنون می توانید، برای مثال، داده ها را صادر کنید. ما دادههای برچسب راه دور و همه پیوندهای مربوط به مسائل و درخواستهای ادغام را صادر کردهایم و آنها را به پایگاه داده تولید منتقل کردهایم. اگر تلفات زیاد باشد، می توانید به سادگی ماکت را تبلیغ کنید و از آن به عنوان اصلی استفاده کنید. اما پس از لحظه ای که ما بهبود یافتیم، همه تغییرات از بین خواهند رفت.
بهتر است از شناسه تراکنش ها به جای مهر زمانی استفاده کنید. ثبت این شناسه ها، به عنوان مثال، برای دستورات DDL (مانند DROP TABLE
)، با استفاده از log_statements = 'ddl'
. اگر شناسه تراکنش داشتیم می گرفتیم recovery_target_xid
و همه چیز را قبل از درخواست به تراکنش انجام داد DELETE
.
بازگشت به کار بسیار ساده است: همه تغییرات را حذف کنید recovery.conf
و postgres را مجددا راه اندازی کنید. به زودی نشانه دوباره هشت ساعت تاخیر خواهد داشت و ما برای مشکلات آینده آماده هستیم.
مزایای بازیابی
با یک کپی تأخیر، به جای یک نسخه پشتیبان سرد، مجبور نیستید ساعت ها را صرف بازیابی کل عکس فوری از بایگانی کنید. به عنوان مثال، ما به پنج ساعت زمان نیاز داریم تا کل بک آپ پایه 2 ترابایتی را دریافت کنیم. و پس از آن شما هنوز هم باید کل WAL روزانه را اعمال کنید تا به حالت دلخواه بازگردید (در بدترین حالت).
یک کپی با تاخیر از دو طریق بهتر از یک نسخه پشتیبان سرد است:
- شما نیازی به دریافت کل نسخه پشتیبان از بایگانی ندارید.
- یک پنجره هشت ساعته ثابت از بخش های WAL وجود دارد که باید تکرار شود.
همچنین، ما دائماً در حال بررسی هستیم که ببینیم آیا WAL میتواند PITR شود یا خیر، و با نظارت بر بکلوگ کپی تأخیرشده، به سرعت متوجه خرابی یا سایر مشکلات بایگانی WAL میشویم.
در این مثال، 50 دقیقه طول کشید تا بازیابی کنیم، یعنی سرعت 110 گیگابایت داده WAL در ساعت بود (بایگانی هنوز روشن بود
خلاصه: جاهایی که کپی تاخیری مفید است (و جایی که نه)
اگر به طور تصادفی داده ها را از دست دادید و متوجه این فاجعه در تاخیر پیکربندی شده شدید، از تکرار تاخیری به عنوان کمک اولیه استفاده کنید.
اما به خاطر داشته باشید: تکرار یک نسخه پشتیبان نیست.
پشتیبان گیری و تکرار اهداف متفاوتی دارند. اگر به طور تصادفی تهیه کنید، یک نسخه پشتیبان سرد مفید خواهد بود DELETE
یا DROP TABLE
. ما یک نسخه پشتیبان از ذخیره سازی سرد تهیه می کنیم و وضعیت قبلی یک جدول یا کل پایگاه داده را بازیابی می کنیم. اما در عین حال درخواست DROP TABLE
تقریباً فوراً در همه کپیها در خوشه کاری تکثیر میشود، بنابراین تکرار منظم در اینجا ذخیره نمیشود. Replication خود پایگاه داده را زمانی که سرورهای جداگانه اجاره میکنند در دسترس نگه میدارد و بار را توزیع میکند.
حتی با یک کپی با تأخیر، گاهی اوقات واقعاً به یک نسخه پشتیبان سرد در مکانی امن نیاز داریم، اگر به طور ناگهانی خرابی مرکز داده، آسیب پنهان یا رویدادهای دیگری رخ دهد که بلافاصله متوجه آن نمیشوید. در اینجا از یک تکرار هیچ معنایی وجود ندارد.
یادداشت. بر
منبع: www.habr.com