WAL-G: PostgreSQL ma'lumotlar bazasini zaxiralash va tiklash

SQL dumplariga zaxira nusxalarini yaratish uzoq vaqtdan beri ma'lum bo'lgan ( pg_dump yoki pg_dumpall) yaxshi fikr emas. PostgreSQL ma'lumotlar bazasini zaxiralash uchun buyruqni ishlatish yaxshiroqdir pg_basebackup, bu WAL jurnallarining ikkilik nusxasini yaratadi. Ammo nusxani yaratish va tiklashning butun jarayonini o'rganishni boshlaganingizda, buning ishlashi uchun kamida bir nechta tricycles yozishingiz kerakligini tushunasiz va yuqorida ham, pastda ham og'riq keltirmasligingiz kerak. Azoblarni engillashtirish uchun WAL-G ishlab chiqilgan.

WAL-G PostgreSQL ma'lumotlar bazasini zaxiralash va tiklash uchun Go'da yozilgan vositadir (va yaqinda MySQL/MariaDB, MongoDB va FoundationDB). U Amazon S3 xotirasi (va analoglari, masalan, Yandex Object Storage), shuningdek, Google Cloud Storage, Azure Storage, Swift Object Storage va oddiygina fayl tizimi bilan ishlashni qo'llab-quvvatlaydi. Butun sozlash oddiy bosqichlardan iborat, ammo bu haqdagi maqolalar Internetda tarqalib ketganligi sababli, boshidan oxirigacha barcha bosqichlarni o'z ichiga olgan to'liq qo'llanma yo'q (Habré-da bir nechta postlar mavjud, lekin u erda ko'p fikrlar o'tkazib yuborilgan).

WAL-G: PostgreSQL ma'lumotlar bazasini zaxiralash va tiklash

Ushbu maqola birinchi navbatda mening bilimlarimni tizimlashtirish uchun yozilgan. Men DBA emasman va biror joyda o'zimni oddiy odamlar tilida ifoda eta olaman, shuning uchun har qanday tuzatishlar qabul qilinadi!

Alohida ta'kidlaymanki, quyida keltirilgan hamma narsa tegishli va Ubuntu 12.3 da PostgreSQL 18.04 uchun sinovdan o'tgan, barcha buyruqlar imtiyozli foydalanuvchi sifatida bajarilishi kerak.

sozlama

Ushbu maqolani yozish paytida WAL-G ning barqaror versiyasi v0.2.15 (2020 yil mart). Bu biz foydalanadigan narsa (lekin agar siz uni asosiy filialdan o'zingiz qurmoqchi bo'lsangiz, github omborida buning uchun barcha ko'rsatmalar mavjud.). Yuklab olish va o'rnatish uchun quyidagilarni qilishingiz kerak:

#!/bin/bash

curl -L "https://github.com/wal-g/wal-g/releases/download/v0.2.15/wal-g.linux-amd64.tar.gz" -o "wal-g.linux-amd64.tar.gz"
tar -xzf wal-g.linux-amd64.tar.gz
mv wal-g /usr/local/bin/

Shundan so'ng siz avval WAL-G ni, keyin esa PostgreSQL ni sozlashingiz kerak.

WAL-G sozlash

Zaxira nusxalarini saqlash misoli uchun Amazon S3 ishlatiladi (chunki u mening serverlarimga yaqinroq va undan foydalanish juda arzon). U bilan ishlash uchun sizga "s3 chelak" va kirish kalitlari kerak.

WAL-G haqidagi oldingi barcha maqolalar muhit o'zgaruvchilari yordamida konfiguratsiyadan foydalanilgan, ammo ushbu nashr bilan sozlamalar quyidagi manzilda joylashgan bo'lishi mumkin. .walg.json fayli postgres foydalanuvchisining uy katalogida. Uni yaratish uchun quyidagi bash skriptini ishga tushiring:

#!/bin/bash

cat > /var/lib/postgresql/.walg.json << EOF
{
    "WALG_S3_PREFIX": "s3://your_bucket/path",
    "AWS_ACCESS_KEY_ID": "key_id",
    "AWS_SECRET_ACCESS_KEY": "secret_key",
    "WALG_COMPRESSION_METHOD": "brotli",
    "WALG_DELTA_MAX_STEPS": "5",
    "PGDATA": "/var/lib/postgresql/12/main",
    "PGHOST": "/var/run/postgresql/.s.PGSQL.5432"
}
EOF
# обязательно меняем владельца файла:
chown postgres: /var/lib/postgresql/.walg.json

Keling, barcha parametrlar haqida bir oz tushuntiraman:

  • WALG_S3_PREFIX – zaxira nusxalari yuklanadigan S3 paqiringizga yo‘l (siz ildizga ham, jildga ham borishingiz mumkin);
  • AWS_ACCESS_KEY_ID - S3 da kirish kaliti (sinov serverida tiklangan taqdirda, bu kalitlar Faqat o'qish siyosatiga ega bo'lishi kerak! Bu qayta tiklash bo'limida batafsil tavsiflangan.);
  • AWS_SECRET_ACCESS_KEY – S3 xotirasida maxfiy kalit;
  • WALG_COMPRESSION_METHOD – siqish usuli, Brotli dan foydalanish yaxshidir (chunki bu oxirgi o'lcham va siqish/dekompressiya tezligi o'rtasidagi oltin o'rtacha);
  • WALG_DELTA_MAX_STEPS - to'liq zaxira yaratishdan oldin "deltalar" soni (ular vaqtni va yuklab olingan ma'lumotlar hajmini tejaydi, lekin tiklash jarayonini biroz sekinlashtirishi mumkin, shuning uchun katta qiymatlardan foydalanish tavsiya etilmaydi);
  • PGDATA - ma'lumotlar bazasi ma'lumotlari bilan katalogga yo'l (buyrug'ini ishga tushirish orqali bilib olishingiz mumkin pg_lsclusters);
  • PGHOST – ma’lumotlar bazasiga ulanish, mahalliy zahira bilan buni ushbu misoldagi kabi unix-rozetkasi orqali amalga oshirgan ma’qul.

Boshqa parametrlarni hujjatlarda topish mumkin: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

PostgreSQL-ni sozlash

Ma'lumotlar bazasi ichidagi arxivator WAL jurnallarini bulutga yuklashi va ularni qayta tiklashi uchun (agar kerak bo'lsa) konfiguratsiya faylida bir nechta parametrlarni o'rnatishingiz kerak. /etc/postgresql/12/main/postgresql.conf. Faqat boshlanuvchilar uchun ishonch hosil qilishingiz kerakkonfiguratsiya qayta yuklanganda DBMS ishdan chiqmasligi uchun quyidagi sozlamalarning hech biri boshqa qiymatlarga o'rnatilmaganligini. Siz ushbu parametrlarni qo'shishingiz mumkin:

#!/bin/bash

echo "wal_level=replica" >> /etc/postgresql/12/main/postgresql.conf
echo "archive_mode=on" >> /etc/postgresql/12/main/postgresql.conf
echo "archive_command='/usr/local/bin/wal-g wal-push "%p" >> /var/log/postgresql/archive_command.log 2>&1' " >> /etc/postgresql/12/main/postgresql.conf
echo “archive_timeout=60” >> /etc/postgresql/12/main/postgresql.conf
echo "restore_command='/usr/local/bin/wal-g wal-fetch "%f" "%p" >> /var/log/postgresql/restore_command.log 2>&1' " >> /etc/postgresql/12/main/postgresql.conf

# перезагружаем конфиг через отправку SIGHUP сигнала всем процессам БД
killall -s HUP postgres

O'rnatilishi kerak bo'lgan parametrlarning tavsifi:

  • wal_level - WAL jurnallarida qancha ma'lumot yozish kerak, "replika" - hamma narsani yozing;
  • arxiv_rejimi – parametrdan buyruq yordamida WAL jurnallarini yuklab olishni yoqish arxiv_buyruq;
  • arxiv_buyruq – tugallangan WAL jurnalini arxivlash buyrug'i;
  • archive_timeout – jurnallarni arxivlash u tugallangandan keyingina amalga oshiriladi, lekin agar sizning serveringiz maʼlumotlar bazasiga ozgina maʼlumotlarni oʻzgartirsa/qoʻshsa, bu yerda soniyalar ichida cheklov oʻrnatish mantiqan toʻgʻri keladi, shundan soʻng arxivlash buyrugʻi majburiy chaqiriladi (Men har soniyada ma'lumotlar bazasiga intensiv ravishda yozaman, shuning uchun men ushbu parametrni ishlab chiqarishda o'rnatmaslikka qaror qildim);
  • tiklash_buyrug'i - WAL jurnalini zaxiradan tiklash buyrug'i, agar "to'liq zaxiralash" (asosiy zaxira) ma'lumotlar bazasida so'nggi o'zgarishlar bo'lmasa ishlatiladi.

Ushbu parametrlarning barchasi haqida batafsil ma'lumotni rasmiy hujjatlar tarjimasida o'qishingiz mumkin: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Zaxira jadvalini sozlash

Nima bo'lishidan qat'iy nazar, uni ishga tushirishning eng qulay usuli bu cron. Bu biz zaxira nusxalarini yaratish uchun sozlaymiz. To'liq zaxira nusxasini yaratish buyrug'i bilan boshlaylik: wal-g'da bu ishga tushirish argumenti zaxira - surish. Avvalo, hamma narsa yaxshi ekanligiga ishonch hosil qilish uchun ushbu buyruqni postgres foydalanuvchisidan qo'lda bajarish yaxshiroqdir (va kirishda xatoliklar yo'q):

#!/bin/bash

su - postgres -c '/usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main'

Ishga tushirish argumentlari ma'lumotlar katalogiga yo'lni ko'rsatadi - sizga shuni eslatib o'tamanki, uni ishga tushirish orqali bilib olishingiz mumkin pg_lsclusters.

Agar hamma narsa xatosiz o'tgan bo'lsa va ma'lumotlar S3 xotirasiga yuklangan bo'lsa, u holda crontab-da davriy ishga tushirishni sozlashingiz mumkin:

#!/bin/bash

echo "15 4 * * *    /usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main >> /var/log/postgresql/walg_backup.log 2>&1" >> /var/spool/cron/crontabs/postgres
# задаем владельца и выставляем правильные права файлу
chown postgres: /var/spool/cron/crontabs/postgres
chmod 600 /var/spool/cron/crontabs/postgres

Ushbu misolda zaxiralash jarayoni har kuni ertalab soat 4:15 da boshlanadi.

Eski zaxira nusxalarini o'chirish

Ehtimol, siz mezozoy davrining barcha zaxira nusxalarini saqlashingiz shart emas, shuning uchun vaqti-vaqti bilan xotirangizni "tozalash" foydali bo'ladi (ikkalasi ham "to'liq zaxiralar", ham WAL jurnallari). Bularning barchasini cron vazifasi orqali bajaramiz:

#!/bin/bash

echo "30 6 * * *    /usr/local/bin/wal-g delete before FIND_FULL $(date -d '-10 days' '+%FT%TZ') --confirm >> /var/log/postgresql/walg_delete.log 2>&1" >> /var/spool/cron/crontabs/postgres
# ещё раз задаем владельца и выставляем правильные права файлу (хоть это обычно это и не нужно повторно делать)
chown postgres: /var/spool/cron/crontabs/postgres
chmod 600 /var/spool/cron/crontabs/postgres

Cron bu vazifani har kuni ertalab soat 6:30 da bajaradi, oxirgi 10 kundagi nusxalardan tashqari hamma narsani (to‘liq zaxiralar, deltalar va WALlar) o‘chirib tashlaydi, lekin kamida bitta zaxira nusxasini qoldiradi. uchun belgilangan sana shunday har qanday nuqta после sanalar PITRga kiritilgan.

Zaxiradan tiklanmoqda

Hech kimga sir emaski, sog'lom ma'lumotlar bazasining kaliti vaqti-vaqti bilan tiklanish va ichidagi ma'lumotlarning yaxlitligini tekshirishdir. Ushbu bo'limda WAL-G yordamida qanday qilib tiklanishni sizga aytaman va keyinroq tekshiruvlar haqida gaplashamiz.

Buni alohida ta'kidlash kerak sinov muhitida qayta tiklash uchun (ishlab chiqarish bo'lmagan hamma narsani) tasodifan zaxira nusxalarini qayta yozmaslik uchun S3-da Faqat o'qish hisob qaydnomasidan foydalanishingiz kerak. WAL-G holatida siz S3 foydalanuvchisi uchun Guruh siyosatida quyidagi huquqlarni o'rnatishingiz kerak (Ta'siri: ruxsat bering): s3: GetObject, s3: ListBucket, s3: GetBucketLocation. Va, albatta, sozlashni unutmang archive_mode=off sozlamalar faylida postgresql.conf, shuning uchun test ma'lumotlar bazasi jimgina zaxiralashni xohlamaydi.

Qayta tiklash qo'lning engil harakati bilan amalga oshiriladi barcha PostgreSQL ma'lumotlarini o'chirish (shu jumladan foydalanuvchilar), shuning uchun quyidagi buyruqlarni bajarayotganda juda ehtiyot bo'ling.

#!/bin/bash

# если есть балансировщик подключений (например, pgbouncer), то вначале отключаем его, чтобы он не нарыгал ошибок в лог
service pgbouncer stop
# если есть демон, который перезапускает упавшие процессы (например, monit), то останавливаем в нём процесс мониторинга базы (у меня это pgsql12)
monit stop pgsql12
# или останавливаем мониторинг полностью
service monit stop
# останавливаем саму базу данных
service postgresql stop
# удаляем все данные из текущей базы (!!!); лучше предварительно сделать их копию, если есть свободное место на диске
rm -rf /var/lib/postgresql/12/main
# скачиваем резервную копию и разархивируем её
su - postgres -c '/usr/local/bin/wal-g backup-fetch /var/lib/postgresql/12/main LATEST'
# помещаем рядом с базой специальный файл-сигнал для восстановления (см. https://postgrespro.ru/docs/postgresql/12/runtime-config-wal#RUNTIME-CONFIG-WAL-ARCHIVE-RECOVERY ), он обязательно должен быть создан от пользователя postgres
su - postgres -c 'touch /var/lib/postgresql/12/main/recovery.signal'
# запускаем базу данных, чтобы она инициировала процесс восстановления
service postgresql start

Qayta tiklash jarayonini tekshirmoqchi bo'lganlar uchun quyida bash sehrining kichik bir qismi tayyorlangan, shuning uchun tiklashda muammolar yuzaga kelganda, skript nolga teng bo'lmagan chiqish kodi bilan ishlamay qoladi. Ushbu misolda, signal fayli o'chirilgan yoki o'chirilganligini aniqlash uchun 120 soniya vaqt (tiklash uchun jami 5 daqiqa) bilan 10 ta tekshirish amalga oshiriladi (bu tiklash muvaffaqiyatli bo'lganligini anglatadi):

#!/bin/bash

CHECK_RECOVERY_SIGNAL_ITER=0
while [ ${CHECK_RECOVERY_SIGNAL_ITER} -le 120 ]
do
    if [ ! -f "/var/lib/postgresql/12/main/recovery.signal" ]
    then
        echo "recovery.signal removed"
        break
    fi
    sleep 5
    ((CHECK_RECOVERY_SIGNAL_ITER+1))
done

# если после всех проверок файл всё равно существует, то падаем с ошибкой
if [ -f "/var/lib/postgresql/12/main/recovery.signal" ]
then
    echo "recovery.signal still exists!"
    exit 17
fi

Muvaffaqiyatli tiklanishdan so'ng, barcha jarayonlarni qayta boshlashni unutmang (pgbouncer/monit va boshqalar).

Qayta tiklashdan keyin ma'lumotlarni tekshirish

Qayta tiklashdan so'ng ma'lumotlar bazasining yaxlitligini tekshirish juda muhim, shunda buzilgan/buzilgan zahira nusxasi paydo bo'lmaydi. Va buni har bir yaratilgan arxiv bilan qilish yaxshidir, lekin qaerda va qanday qilish faqat sizning tasavvuringizga bog'liq (siz har soatda individual serverlarni ko'tarishingiz yoki CIda tekshirishingiz mumkin). Lekin hech bo'lmaganda ma'lumotlar bazasidagi ma'lumotlar va indekslarni tekshirish kerak.

Ma'lumotni tekshirish uchun uni dump orqali ishga tushirish kifoya, ammo ma'lumotlar bazasini yaratishda nazorat summalari yoqilgan bo'lishi yaxshiroqdir (ma'lumotlarni tekshirish summalari):

#!/bin/bash

if ! su - postgres -c 'pg_dumpall > /dev/null'
then
    echo 'pg_dumpall failed'
    exit 125
fi

Indekslarni tekshirish uchun - mavjud amcheck moduli, keling, buning uchun sql so'rovini olamiz WAL-G sinovlari va uning atrofida bir oz mantiq yarating:

#!/bin/bash

# добавляем sql-запрос для проверки в файл во временной директории
cat > /tmp/amcheck.sql << EOF
CREATE EXTENSION IF NOT EXISTS amcheck;
SELECT bt_index_check(c.oid), c.relname, c.relpages
FROM pg_index i
JOIN pg_opclass op ON i.indclass[0] = op.oid
JOIN pg_am am ON op.opcmethod = am.oid
JOIN pg_class c ON i.indexrelid = c.oid
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE am.amname = 'btree'
AND c.relpersistence != 't'
AND i.indisready AND i.indisvalid;
EOF
chown postgres: /tmp/amcheck.sql

# добавляем скрипт для запуска проверок всех доступных баз в кластере
# (обратите внимание что переменные и запуск команд – экранированы)
cat > /tmp/run_amcheck.sh << EOF
for DBNAME in $(su - postgres -c 'psql -q -A -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;" ')
do
    echo "Database: ${DBNAME}"
    su - postgres -c "psql -f /tmp/amcheck.sql -v 'ON_ERROR_STOP=1' ${DBNAME}" && EXIT_STATUS=$? || EXIT_STATUS=$?
    if [ "${EXIT_STATUS}" -ne 0 ]
    then
        echo "amcheck failed on DB: ${DBNAME}"
        exit 125
    fi
done
EOF
chmod +x /tmp/run_amcheck.sh

# запускаем скрипт
/tmp/run_amcheck.sh > /tmp/amcheck.log

# для проверки что всё прошло успешно можно проверить exit code или grep’нуть ошибку
if grep 'amcheck failed' "/tmp/amcheck.log"
then
    echo 'amcheck failed: '
    cat /tmp/amcheck.log
    exit 125
fi

Xulosa

Men Andrey Borodinga nashrni tayyorlashda ko'rsatgan yordami va WAL-G ni rivojlantirishga qo'shgan hissasi uchun alohida minnatdorchiligimni bildirmoqchiman!

Bu eslatmani yakunlaydi. Umid qilamanki, men o'rnatishning qulayligi va kompaniyangizda ushbu vositadan foydalanishning katta imkoniyatlarini etkaza oldim. Men WAL-G haqida ko'p eshitdim, lekin o'tirib, tushunishga vaqtim bo'lmadi. Va uni uyda amalga oshirganimdan so'ng, bu maqola mendan chiqdi.

Alohida ta'kidlash joizki, WAL-G quyidagi ma'lumotlar bazalari bilan ham ishlashi mumkin:

Manba: www.habr.com

a Izoh qo'shish