نستمر في التعرف على أداة pg_probackup .
في الجزء الأول ، قمنا بتثبيت pg_probackup ، وإنشاء مثيل وتهيئته ، وأخذ نسختين احتياطيتين - كاملتين ومتزايدتين في وضع DELTA ، وتعلمنا كيفية عرض وتغيير تكوين المثيل. حصلنا على قائمة بالنسخ الاحتياطية ، وكتبنا نصًا (bkp_base.sh) يدعم الكتلة ويرسل نتائج آخر عملية نسخ احتياطي إلى نظام المراقبة. اليوم سوف نتعامل مع مهام لا تقل إثارة للاهتمام.
المشكلة 2
معطى: لدينا خادمان ، في الأول لدينا قاعدة بياناتنا (hostname srv_db1 ، user postgres) ، والثاني سنخزن النسخ الاحتياطية (hostname srv_bkp ، user backup_user). ولكن بالإضافة إلى النسخ الاحتياطية على نفس الخادم ، سنقوم بتخزين نسخ من سجلات التسجيل المسبق حتى نتمكن من استعادة نقطة زمنية عشوائية (استرداد نقطة في الوقت) خلال الأيام الثلاثة الماضية.
الحل:
لكي نتمكن من الاستعادة إلى النقطة المحددة في الوقت المناسب (نقطة الاستعادة) ، يجب أن يكون لدينا نسخة احتياطية قبل نقطة الاستعادة ، وكذلك جميع ملفات WAL من لحظة بدء النسخ الاحتياطي إلى نقطة الاستعادة.
لدينا بالفعل نسخ احتياطية ، ويبقى تكوين أرشفة WAL على srv_bkp.
قم بالاتصال بـ srv_db1 باستخدام مستخدم postgres وقم بتنفيذ الأوامر التالية:
ssh-keygen -t rsa
ssh-copy-id backup_user@srv_bkp
دعنا نعدل الملف ~ / .ssh / autorized_keys إلى srv_bkp:
command="pg_probackup-12 agent" ssh-rsa AAAA....
بالعودة إلى srv_db1 ، تحتاج إلى تمكين وضع الأرشيف (archive_mode) وتكوين معلمة archive_command. يحتوي على أمر لإجراء نسخ احتياطي لقطعة WAL كاملة.
psql -c 'show archive_mode'
إذا عاد ، فقم بالتغيير إلى on
psql -c 'alter system set archive_mode = on'
لكي يتم تطبيق التغيير ، تحتاج إلى إعادة تشغيل PostgreSQL ، ولكن في الوقت الحالي سنؤجل هذا الإجراء ونقوم بتهيئة متغير واحد آخر.
إذا كان تدفق ملفات WAL كبيرًا بدرجة كافية ، فقد تنفد مساحة خادم النسخ الاحتياطي قريبًا ، لذا يمكننا إدراج خيار الضغط في سطر archive_command ، فسيتم ضغط ملفات السجل قبل إرسالها إلى srv_bkp. ولن نحتاج إلى القلق بشأن حقيقة أن هذه الملفات ستحتاج إلى فك حزمها بشكل منفصل أثناء الاسترداد - يمكن أن يعمل pg_probackup مع الملفات المضغوطة.
alter system set archive_command = 'pg_probackup-12 archive-push -B /home/backup_user/backup_db --instance=db1 --wal-file-path=%p --wal-file-name=%f --remote-host=srv_bkp --remote-user=backup_user --compress';
الآن يمكنك إعادة التشغيل.
ما فعلناه في المهمة الأولى يسمى النسخ الاحتياطي دون اتصال. يطلق عليه ذلك لأن هذه النسخة تحتوي على جميع ملفات WAL اللازمة لاستعادتها. في المهمة الحالية ، ننتقل من النسخ غير المتصلة بالإنترنت إلى النسخ الأرشيفية ، لا تحتوي هذه النسخ على السجلات الضرورية بداخلها ، لكن هذا لا يهم ، لأننا سنحفظ جميع ملفات WAL التي نحتاجها في أرشيف. عند الاستعادة من النسخ الاحتياطية ، سيتم نسخ ملفات WAL من الأرشيف.
نظرًا لأننا في الحالة قيد النظر ننتقل من النسخ الاحتياطية دون اتصال (التي تم إجراؤها في وضع الدفق) إلى المؤرشفة (في وضع الأرشيف) ، فقد تنشأ حالة قمنا فيها بعمل نسخة عندما لم يتم تمكين وضع الأرشيف بعد ، وبعد ذلك ظهرت بالفعل بعض مقاطع WAL إزالة. هذا يعني أن النسخ الاحتياطي الأول بعد التبديل إلى وضع الأرشيف لا يمكن إجراؤه في وضع PAGE ، لأن قد لا يكون مقطع WAL في الأرشيف بين النسخة السابقة والحالية مكتملاً.
لنفعل ذلك باستخدام البرنامج النصي الذي تم إنشاؤه في المهمة الأولى:
./bkp_base.sh DELTA
ثم سننشئ أول نسخة احتياطية لنا في وضع PAGE
./bkp_base.sh PAGE
اسمحوا لي أن أذكرك أن هناك ثلاثة أوضاع تزايدية متاحة: PAGE و DELTA و PTRACK. تختلف عن بعضها البعض في طرق الحصول على المعلومات الضرورية حول الصفحات التي تم تغييرها:
لنفكر الآن ، أن النسخة الاحتياطية ، لتتمكن من الاسترداد منها ، تحتاج إلى ملفات WAL التي تم إنشاؤها أثناء إنشاء النسخة الاحتياطية. أولئك. إذا قمنا بعمل نسخ احتياطي تزايدي لمدة 30 دقيقة وخلال هذه الدقائق 30 تم إنشاء 10 غيغابايت من WAL ، فلن نحتاج إلا إلى 10 غيغابايت فقط حتى نتمكن من التعافي منها باستمرار. جميع ملفات WAL الأخرى مطلوبة فقط لأغراض الاسترداد في وقت واحد.
أشارت المهمة إلى أننا نريد أن نكون قادرين على التعافي في أي وقت من الأوقات خلال الأيام الثلاثة الماضية. أي أنه يجب حفظ كل WAL لهذه الفترة ، بالإضافة إلى أنه من الضروري حفظ كل WAL اللازمة للاستعادة من النسخ الاحتياطية السابقة ، لكننا لا نحتاج إلى تخزين جميع ملفات WAL الأخرى!
وإذا تمكنا من استخدام الأمر find لإزالة WALs المتقادمة ، وإضافة mtime و -exec rm {} إليها ، فإن تحديد مقطع WAL المطلوب لاستعادة نسخة احتياطية معينة باستمرار لن يصبح مهمة سهلة. من الجيد أن المطورين فكروا في هذا الأمر وقاموا بإضافة معلمة --wal-deep ، والتي من خلالها يمكنك ضبط عمق تخزين WAL ، المحسوب في النسخ الاحتياطية.
يمكن وصفه بشكل تخطيطي على النحو التالي:
يرجى ملاحظة أنه الآن في مكان ما في منتصف يوم السبت ، مما يعني أنه يمكننا حذف جميع ملفات WAL غير الضرورية لاستعادة النسخ الاحتياطية التي مضى عليها أكثر من ثلاثة أيام (اللون البني على الرسم البياني). يتم تمييز أسماء WALs التي لا تزال مطلوبة باللون الأصفر. قد يظهر هنا سؤال منطقي - ولكن بعد كل شيء ، إنه بالفعل منتصف يوم السبت ، مما يعني أن بعض السجلات الصباحية التي تم إنشاؤها يوم الأربعاء لم تعد ضرورية ، ويمكن حذفها. نعم ، هذا صحيح ، ويمكنك تكوين حذف WAL الزائد كل دقيقة على الأقل ، ولكن في مقالتنا سنحذف السجلات إلى جانب إنشاء النسخ الاحتياطية ، لذلك على الرغم من حقيقة أنها لم تعد تدخل في سياسة الاحتفاظ ، سيتم حذفها عند إنشاء النسخة الاحتياطية التالية. ...
قم بتغيير إعدادات مثيل db1 - أضف عمر ملفات WAL
pg_probackup set-config --instance db1 --wal-depth=3
دعنا نتحقق من تطبيق الإعدادات:
pg_probackup show-config --instance=db1 | grep wal-depth
أضف علامة --delete-wal إلى أمر النسخ الاحتياطي في البرنامج النصي bkp_base.sh ، وقم أيضًا بإزالة مفتاح التبديل --stream ، لأننا نحول من النسخ الاحتياطية دون اتصال إلى النسخ المؤرشفة
pg_probackup backup --instance=db1 -j 2 --progress -b $1 --compress --delete-expired --delete-wal
في الوقت الحالي ، قمنا بتكوين إنشاء نسخ احتياطية للأرشيف على خادم منفصل. أيضًا ، تتم إضافة ملفات السجل هنا ، مما يمنحنا الفرصة لاستخدام الاسترداد ليس فقط لنسخة احتياطية محددة ، ولكن أيضًا لإجراء استرداد في الوقت المناسب - استرداد إلى نقطة زمنية محددة.
نظرًا لأن لدينا الآن أرشيفًا لملفات WAL ، يمكننا استخدام وضع PAGE لإنشاء نسخ احتياطية إضافية ، دعني أذكرك أنه في هذا الوضع ، لا يتم حساب التغييرات المتعلقة بالنسخ الاحتياطي السابق بواسطة ملفات البيانات ، ولكن بواسطة WAL المتراكمة منذ النسخ الاحتياطي السابق.
PS للأغراض التعليمية فقط! لنقم بإنشاء جدول في قاعدة البيانات على خادم srv_db1:
psql -c 'create table timing(time_now timestamp with time zone)'
ثم اكتب السطر التالي إلى crontab:
* * * * * psql -c 'insert into timing(select now())'
في كل دقيقة ، سيتم تسجيل معلومات حول الوقت الحالي في قاعدة البيانات ، وستكون هذه المعلومات مفيدة لنا عندما نعيد إلى نقطة زمنية.
مشكلة 3
بالنظر إلى:
لدينا خادمان ، في الأول لدينا قاعدة بياناتنا (اسم المضيف srv_db1 ، مستخدم postgres) ، في الثاني يخزن النسخ الاحتياطية المؤرشفة وملفات WAL (اسم المضيف srv_bkp ، المستخدم backup_user). يظهر خادم آخر srv_db2 في بيئتنا (مستخدم postgres) ، حيث يتعين علينا نشر نسخة طبق الأصل من المجموعة الخاصة بنا وإعادة تكوين pg_probackup بحيث يأخذ نسخًا احتياطية من النسخة المتماثلة.
القرار:
الإنترنت مليء بالأوصاف حول كيفية إنشاء نسخ متماثلة في PostgreSQL ، كل ما عليك فعله هو دفع "إنشاء نسخة متماثلة في PostgreSQL" إلى محرك البحث - اختر ، لا أريد ذلك! هناك وثائق ومقالات وحتى دروس فيديو. وكل هذه الطرق جيدة ، لكنها عادة لا تأخذ في الاعتبار أن لدينا بالفعل نسخ احتياطية. نريد إنشاء نسخة متماثلة باستخدام نسخة احتياطية ، لذلك نقوم بإزالة حمل القراءة من الرئيسي. أي أن خادم الإنتاج الخاص بنا لن يدرك أنه يتم إنشاء نسخة متماثلة في مكان ما بجواره (هذا ، بالطبع ، مع الحجوزات - هنا يجب إنشاء فتحة النسخ وتعيين حقوق الوصول ، ولكن أثناء قيامنا بإنشاء نسخة طبق الأصل ، لا يوجد حمل إضافي على الرئيسي لن يكون).
قمنا بإعداد الوصول عن طريق المفاتيح بين خادمي srv_bkp و srv_db2 ، وقمنا بتثبيت PostgreSQL و pg_probackup على srv_db2 (لقد فعلنا كل شيء باستثناء تثبيت PostgreSQL أثناء المهمة الأولى ، ولكن إذا كانت لديك أي أسئلة حول تثبيت نظام إدارة قواعد البيانات ، فقم بإلقاء نظرة هنا ).
انتقل إلى srv_db2
ssh-keygen -t rsa
ssh-copy-id backup_user@srv_bkp
انتقل إلى srv_bkp
ssh-copy-id postgres@srv_db2
دعنا نشغل بجنون العظمة الداخلي لدينا ونعدل ~ / .ssh / autorized_keys - insert
command="pg_probackup-12 agent"
قبل مفاتيح جديدة.
يعد استخدام ملفات WAL أبطأ بكثير من الاستعادة من نسخة احتياطية ، لذلك دعونا ننشئ نسخة احتياطية تزايدية أخرى - اتصل بخادم srv_bkp باستخدام backup_user وقم بتشغيل الأمر:
pg_probackup backup --instance=db1 -j 2 --progress -b PAGE --compress
لماذا لم نستخدم النص الذي أنشأناه؟ الحقيقة هي أننا أضفنا سابقًا خيار --delete-wal إلى البرنامج النصي ، أي بعد إنشاء هذه النسخة الاحتياطية ، لن نتمكن من استعادة نقطة زمنية كانت قبل ثلاثة أيام. ولكن إذا تركنا هذه النسخة الاحتياطية ، فإن النسخة الاحتياطية التالية التي تم إنشاؤها عن طريق تشغيل البرنامج النصي الخاص بنا ستظل تترك WAL خلال اليومين الماضيين فقط ، أي بعد التعافي من هذه النسخة الاحتياطية ، فمن المنطقي حذفها.
نجعل الشفاء:
time pg_probackup restore --instance=db1 -D /var/lib/pgsql/12/data -j 2 --restore-as-replica --progress --remote-proto=ssh --remote-host=srv_db2 --archive-host=srv_bkp --archive-user=backup_user --log-level-console=log --log-level-file=verbose --log-filename=restore_rep.log
يجب أن يكون دليل البيانات / var / lib / pgsql / 12 / فارغًا ، بالإضافة إلى ذلك ، على خادم srv_db1 ، تحتاج إلى إجراء تغييرات على pg_hba.conf - للسماح بالوصول من خادم srv_db2 باستخدام بروتوكول النسخ المتماثل.
host replication all srv_db2 md5
نعيد قراءة التكوين:
psql -c 'select pg_reload_conf()'
التحقق من الأخطاء المطبعية:
psql -c 'select * from pg_hba_file_rules'
قم بإنشاء ملف ~ / .pgpass على srv_db2 ، حيث نحدد أذونات الاتصال في srv_db1 ولكن هذه المرة مع قاعدة النسخ المتماثل وابدأ PostgreSQL.
srv_db1:5432:replication:backup:Strong_PWD
ودعنا نغير حقوقه إلى 600:
chmod 600 ~/.pgpass
نبدأ الكتلة على srv_db2.
دعونا نتحقق من أن كل شيء يعمل بشكل جيد. سوف نستخدم الاحتمالات التالية لهذا الغرض.
نحن ننظر في ملف سجل النسخة المتماثلة فيه ، في مكان ما بالقرب من النهاية ، يجب أن يظهر السطر التالي:
Database system is ready to accept read only connections
psql -c 'select pg_is_in_recovery()'
يجب أن تعود t
الآن لنقم بإنشاء لوحة t1 على المعالج:
srv_db1: psql -c 'create table t1()'
دعنا نتحقق مما إذا كان قد ظهر في النسخة المتماثلة.
srv_db2: psql -c '\d'
اللوحة في مكانها ، ثم يعمل النسخ المتماثل. نزيل اللوحة على السيد.
srv_db1: psql -c 'drop table t1'
بالطبع ، في قاعدة بيانات حقيقية ، الآن سيكون من الضروري إنشاء فتحة نسخ متماثلة على الشريحة الرئيسية وتكوين النسخة المتماثلة بحيث تنتقل إلى الشريحة الرئيسية من خلال هذه الفتحة ، لكن موضوع مقالتنا ليس نسخًا متماثلة ، بل نسخًا احتياطية ، لذلك سنستمر.
لذا ، تعمل النسخة المتماثلة معنا ، إذا لزم الأمر ، يمكننا التبديل إلى النسخة المتماثلة ، لكن دعنا نسأل أنفسنا سؤالًا - هل يمكننا القيام بعمل أفضل؟
بالتأكيد تستطيع. لماذا نحتاج إلى أخذ نسخ احتياطية من البرنامج الرئيسي بينما يمكننا إزالة حمل القراءة من البرنامج الرئيسي ونقله إلى نسخة متماثلة؟
الحذر! يجب مراقبة تأخر النسخ المتماثلة ، وإلا فقد يتم إخراجها بحيث لا تعرف أن النسخة المطابقة تأخرت وستستمر في النسخ الاحتياطي من تأخر النسخ المتماثل.
لنفعل ذلك!
نجري تغييرات في إعدادات المجموعة على خوادم srv_db1 و srv_db2:
alter system set archive_timeout=180;
select pg_reload_conf();
انتقل إلى srv_bkp وقم بتغيير قيمة معلمة المضيف البعيد:
pg_probackup set-config --instance db1 --remote-host=srv_db2
نجري تغييرات على .pgpass على خادم srv_bkp - أضف سلاسل الاتصال إلى خادم srv_db2:
srv_db2:5432:replication:backup:Strong_PWD
srv_db2:5432:backupdb:backup:Strong_PWD
ودعونا نحاول أخذ نسخة احتياطية أخرى.
srv_bkp: ./bkp_base.sh PAGE
نرى أن النسخ الاحتياطي قد نجح.
حلت المشكلة!
سيخصص الجزء التالي للاستعادة من النسخ الاحتياطية: سننظر في خيارات الاسترداد المختلفة ، ونتعلم كيفية الاستعادة إلى نسخة احتياطية محددة ، إلى نقطة زمنية ، والتعرف على عمليات الاستعادة الجزئية والتزايدية.