WAL-G: pag-backup ug pagbawi sa PostgreSQL DBMS

Dugay nang nahibal-an nga ang paghimo sa mga backup sa SQL dumps (gamit ang pg_dump o pg_dumpall) dili maayo nga ideya. Aron i-backup ang PostgreSQL DBMS, mas maayo nga gamiton ang command pg_basebackup, nga naghimo ug binary nga kopya sa WAL logs. Apan kung magsugod ka sa pagtuon sa tibuuk nga proseso sa paghimo og usa ka kopya ug pag-uli, imong masabtan nga kinahanglan nimo nga magsulat bisan usa ka pares nga mga traysikol aron kini molihok ug dili hinungdan sa imong kasakit sa ibabaw ug sa ubos. Aron maibanan ang pag-antos, ang WAL-G gimugna.

WAL-G usa ka himan nga gisulat sa Go alang sa pag-back up ug pagpasig-uli sa mga database sa PostgreSQL (ug mas bag-o MySQL/MariaDB, MongoDB ug FoundationDB). Gisuportahan niini ang pagtrabaho sa storage sa Amazon S3 (ug mga analogue, pananglitan, Yandex Object Storage), ingon man ang Google Cloud Storage, Azure Storage, Swift Object Storage ug yano sa file system. Ang bug-os nga pag-setup naggikan sa yano nga mga lakang, apan tungod sa kamatuoran nga ang mga artikulo bahin niini nagkatag sa tibuuk nga Internet, wala’y kompleto nga manual kung giunsa nga maglakip sa tanan nga mga lakang gikan sa pagsugod hangtod sa katapusan (adunay daghang mga post sa Habré, apan daghang mga punto ang wala didto).

WAL-G: pag-backup ug pagbawi sa PostgreSQL DBMS

Kini nga artikulo gisulat sa panguna aron ma-systematize ang akong kahibalo. Dili ako usa ka DBA ug makapahayag ako sa akong kaugalingon sa lengguwahe sa mga layko bisan asa, busa ang bisan unsang mga pagtul-id gidawat!

Gilain, akong namatikdan nga ang tanan sa ubos adunay kalabotan ug gisulayan alang sa PostgreSQL 12.3 sa Ubuntu 18.04, ang tanan nga mga mando kinahanglan ipatuman ingon usa ka pribilihiyo nga tiggamit.

Pag-instalar

Sa panahon sa pagsulat niini nga artikulo, ang lig-on nga bersyon sa WAL-G mao ang v0.2.15 (Marso 2020). Kini ang atong gamiton (apan kung gusto nimo nga tukuron kini sa imong kaugalingon gikan sa master branch, nan ang github repository adunay tanan nga mga panudlo alang niini). Aron ma-download ug ma-install kinahanglan nimo buhaton:

#!/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/

Pagkahuman niini, kinahanglan nimo nga i-configure una ang WAL-G, ug dayon ang PostgreSQL mismo.

Pagpahimutang sa WAL-G

Alang sa usa ka pananglitan sa pagtipig sa mga backup, ang Amazon S3 gamiton (kay mas duol sa akong mga server ug barato kaayo ang paggamit niini). Aron magamit kini, kinahanglan nimo ang usa ka "s3 bucket" ug mga yawe sa pag-access.

Ang tanan nga miaging mga artikulo bahin sa WAL-G migamit sa pag-configure gamit ang mga variable sa palibot, apan sa kini nga pagpagawas ang mga setting mahimong makit-an sa .walg.json file sa home directory sa postgres user. Aron mahimo kini, pagdagan ang mosunud nga script sa bash:

#!/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

Tugoti ako nga ipasabut ang gamay bahin sa tanan nga mga parameter:

  • WALG_S3_PREFIX – ang dalan paingon sa imong S3 bucket diin ang mga backup i-upload (mahimo nimo sa root o sa usa ka folder);
  • AWS_ACCESS_KEY_ID - access key sa S3 (sa kaso sa pagkaayo sa usa ka test server, kini nga mga yawe kinahanglan nga adunay ReadOnly Policy! Kini gihulagway sa mas detalyado sa seksyon sa pagbawi.);
  • AWS_SECRET_ACCESS_KEY - sekreto nga yawe sa pagtipig sa S3;
  • WALG_COMPRESSION_METHOD – pamaagi sa compression, mas maayo nga gamiton ang Brotli (tungod kay kini ang bulawan nga kahulogan tali sa katapusang gidak-on ug compression/decompression speed);
  • WALG_DELTA_MAX_STEPS - ang gidaghanon sa mga "delta" sa wala pa maghimo usa ka bug-os nga backup (nagtipig sila sa oras ug ang gidak-on sa na-download nga datos, apan mahimo’g gamay nga mapahinay ang proseso sa pagbawi, mao nga dili maayo nga mogamit daghang mga kantidad);
  • PGDATA – dalan sa direktoryo uban sa imong database data (mahibal-an nimo pinaagi sa pagpadagan sa mando pg_lsclusters);
  • PGHOST - pagkonektar sa database, nga adunay lokal nga backup mas maayo nga buhaton kini pinaagi sa usa ka unix-socket sama sa kini nga pananglitan.

Ang ubang mga parameter makita sa dokumentasyon: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

Pag-set up sa PostgreSQL

Aron ang archiver sa sulod sa database maka-upload sa mga WAL log sa panganod ug ibalik kini gikan kanila (kung gikinahanglan), kinahanglan nimo nga magbutang og daghang mga parameter sa configuration file /etc/postgresql/12/main/postgresql.conf. Para lang sa pagsugod kinahanglan nimong sigurohonnga walay bisan usa sa mga setting sa ubos ang gibutang sa bisan unsa nga lain nga mga bili, aron nga kung ang configuration i-reload, ang DBMS dili ma-crash. Mahimo nimong idugang kini nga mga parameter gamit ang:

#!/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

Deskripsyon sa mga parameter nga itakda:

  • wal_level – pila ka impormasyon ang isulat sa WAL logs, “replica” – isulat ang tanan;
  • archive_mode - i-enable ang pag-download sa mga WAL log gamit ang command gikan sa parameter archive_command;
  • archive_command - sugo alang sa pag-archive sa usa ka kompleto nga WAL log;
  • archive_timeout - Ang pag-archive sa mga troso gihimo lamang kung kini nahuman, apan kung ang imong server nagbag-o / nagdugang gamay nga datos sa database, nan makatarunganon nga magbutang usa ka limitasyon dinhi sa mga segundo, pagkahuman ang mando sa pag-archive tawgon nga kusog (Madasigon kong nagsulat sa database matag segundo, mao nga nakahukom ko nga dili ibutang kini nga parameter sa produksyon);
  • restore_command – ang sugo nga ibalik ang WAL log gikan sa usa ka backup gamiton kon ang “full backup” (base backup) kulang sa pinakabag-o nga mga kausaban sa database.

Mahimo nimong mabasa ang dugang bahin sa tanan niini nga mga parameter sa paghubad sa opisyal nga dokumentasyon: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Paghimo og backup nga iskedyul

Bisan unsa ang isulti sa usa, ang labing kombenyente nga paagi sa pagpadagan niini mao ang cron. Kini ang atong i-configure aron makahimo og mga backup. Magsugod kita sa sugo sa paghimo og bug-os nga backup: sa wal-g kini ang argumento sa paglansad backup-push. Apan una, mas maayo nga ipadagan kini nga mando nga mano-mano gikan sa tiggamit sa postgres aron masiguro nga maayo ang tanan (ug wala’y mga sayup sa pag-access):

#!/bin/bash

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

Ang mga argumento sa paglansad nagpaila sa agianan sa direktoryo sa datos - Gipahinumdoman ko ikaw nga makit-an nimo kini pinaagi sa pagdagan pg_lsclusters.

Kung ang tanan wala’y mga kasaypanan ug ang datos gikarga sa S3 storage, nan mahimo nimong i-configure ang periodic launch sa crontab:

#!/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

Niini nga pananglitan, ang proseso sa pag-backup magsugod kada adlaw sa 4:15 am.

Pagtangtang sa daan nga mga backup

Lagmit, dili nimo kinahanglan nga tipigan ang tanan nga mga pag-backup gikan sa panahon sa Mesozoic, busa kini mapuslanon nga matag karon ug unya "limpyohan" ang imong pagtipig (parehong "bug-os nga pag-backup" ug WAL nga mga log). Buhaton namo kini tanan pinaagi sa usa ka cron nga buluhaton:

#!/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

Pagabuhaton ni Cron kini nga buluhaton kada adlaw sa alas 6:30 sa buntag, pagtangtang sa tanan (bug-os nga backup, delta ug WAL) gawas sa mga kopya sa miaging 10 ka adlaw, apan magbilin bisan usa ka backup. sa gipiho nga petsa aron ang bisan unsang punto human sa Ang mga petsa gilakip sa PITR.

Pag-uli gikan sa usa ka backup

Dili kini sekreto nga ang yawe sa usa ka himsog nga database mao ang matag karon nga pagpahiuli ug pag-verify sa integridad sa datos sa sulod. Isulti ko kanimo kung giunsa ang pagbawi gamit ang WAL-G sa kini nga seksyon, ug maghisgot kami bahin sa mga tseke sa ulahi.

Kini mao ang bili noting gilain nga aron mapasig-uli sa usa ka pagsulay nga palibot (tanan nga dili produksiyon) kinahanglan nimo nga mogamit usa ka Read Only nga account sa S3 aron dili aksidente nga ma-overwrite ang mga backup. Sa kaso sa WAL-G, kinahanglan nimong itakda ang mosunod nga mga katungod para sa S3 user sa Group Policy (Epekto: Tugoti): s3: GetObject, s3: ListBucket, s3:GetBucketLocation. Ug, siyempre, ayaw kalimot sa pag-set archive_mode=off sa settings file postgresql.conf, aron ang imong test database dili gusto nga i-back up sa hilom.

Ang pagpahiuli gihimo sa usa ka gamay nga paglihok sa kamot pagtangtang sa tanang datos sa PostgreSQL (lakip ang mga tiggamit), busa palihug pag-amping pag-ayo kung imong gipadagan ang mosunod nga mga mando.

#!/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

Alang niadtong gusto nga susihon ang proseso sa pagbawi, ang usa ka gamay nga piraso sa bash magic giandam sa ubos, aron sa kaso sa mga problema sa pagkaayo, ang script mag-crash sa usa ka non-zero exit code. Niini nga pananglitan, 120 ka mga tseke ang gihimo nga adunay timeout nga 5 segundos (sa kinatibuk-an nga 10 ka minuto alang sa pagkaayo) aron mahibal-an kung ang signal file natangtang (kini nagpasabut nga ang pagkaayo malampuson):

#!/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

Human sa malampuson nga pagkaayo, ayaw kalimot sa pagsugod sa tanan nga mga proseso balik (pgbouncer/monit, ug uban pa).

Pagsusi sa data human sa pagkaayo

Kinahanglan nga susihon ang integridad sa database pagkahuman sa pagpasig-uli, aron ang usa ka sitwasyon nga adunay usa ka guba / hiwi nga backup dili motungha. Ug mas maayo nga buhaton kini sa matag gimugna nga archive, apan asa ug sa unsang paagi nagdepende lamang sa imong imahinasyon (mahimo nimong ipataas ang tagsa-tagsa nga mga server matag oras o magpadagan sa tseke sa CI). Apan sa labing gamay, gikinahanglan nga susihon ang mga datos ug mga indeks sa database.

Aron masusi ang datos, igo na ang pagpadagan niini pinaagi sa usa ka dump, apan mas maayo nga sa paghimo sa database adunay mga checksum nga gipagana (mga pagsusi sa datos):

#!/bin/bash

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

Aron masusi ang mga indeks - anaa amcheck module, atong kuhaon ang sql nga pangutana alang niini gikan sa Mga pagsulay sa WAL-G ug paghimo og gamay nga lohika sa palibot niini:

#!/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

Sa pagsumada

Gusto nakong ipahayag ang akong pasalamat kang Andrey Borodin sa iyang tabang sa pag-andam sa publikasyon ug espesyal nga pasalamat sa iyang kontribusyon sa pagpalambo sa WAL-G!

Kini nagtapos niini nga nota. Nanghinaut ko nga nahatag nako ang kadali sa pag-setup ug ang dako nga potensyal sa paggamit niini nga himan sa imong kompanya. Daghan kog nadunggan bahin sa WAL-G, pero wala koy igong panahon sa paglingkod ug paghuna-huna niini. Ug pagkahuman nako kini gipatuman sa balay, kini nga artikulo migawas gikan kanako.

Sa tinuud, angay nga matikdan nga ang WAL-G mahimo usab nga magtrabaho kauban ang mosunud nga DBMS:

Source: www.habr.com

Idugang sa usa ka comment