WAL-G: ื’ื™ื‘ื•ื™ื™ื ื•ืฉื—ื–ื•ืจ ืฉืœ PostgreSQL DBMS

ื–ื” ื–ืžืŸ ืจื‘ ื™ื“ื•ืข ืฉื‘ื™ืฆื•ืข ื’ื™ื‘ื•ื™ื™ื ืœ-SQL dumps (ื‘ืืžืฆืขื•ืช pg_dump ืื• pg_dumpall) ื–ื” ืœื ืจืขื™ื•ืŸ ื˜ื•ื‘. ื›ื“ื™ ืœื’ื‘ื•ืช ืืช PostgreSQL DBMS, ืขื“ื™ืฃ ืœื”ืฉืชืžืฉ ื‘ืคืงื•ื“ื” pg_basebackup, ืืฉืจ ื™ื•ืฆืจ ืขื•ืชืง ื‘ื™ื ืืจื™ ืฉืœ ื™ื•ืžื ื™ WAL. ืื‘ืœ ื›ืฉืชืชื—ื™ืœ ืœืœืžื•ื“ ืืช ื›ืœ ื”ืชื”ืœื™ืš ืฉืœ ื™ืฆื™ืจืช ื”ืขืชืงื” ื•ืฉื—ื–ื•ืจ, ืชื‘ื™ืŸ ืฉืืชื” ืฆืจื™ืš ืœื›ืชื•ื‘ ืœืคื—ื•ืช ื›ืžื” ืชืœืช ืื•ืคืŸ ื›ื“ื™ ืฉื–ื” ื™ืขื‘ื•ื“ ื•ืœื ื™ื’ืจื•ื ืœืš ืœื›ืื‘ื™ื ื’ื ืœืžืขืœื” ื•ื’ื ืœืžื˜ื”. ื›ื“ื™ ืœื”ืงืœ ืขืœ ื”ืกื‘ืœ ืคื•ืชื— WAL-G.

WAL-G ื”ื•ื ื›ืœื™ ืฉื ื›ืชื‘ ื‘-Go ืœื’ื™ื‘ื•ื™ ื•ืฉื—ื–ื•ืจ ืžืกื“ื™ ื ืชื•ื ื™ื ืฉืœ PostgreSQL (ื•ืœืื—ืจื•ื ื” MySQL/MariaDB, MongoDB ื•-FoundationDB). ื”ื•ื ืชื•ืžืš ื‘ืขื‘ื•ื“ื” ืขื ืื—ืกื•ืŸ Amazon S3 (ื•ืื ืœื•ื’ื™ื, ืœืžืฉืœ, Yandex Object Storage), ื›ืžื• ื’ื Google Cloud Storage, Azure Storage, Swift Object Storage ื•ืคืฉื•ื˜ ืขื ืžืขืจื›ืช ื”ืงื‘ืฆื™ื. ื”ื”ื’ื“ืจื” ื›ื•ืœื” ืžืกืชื›ืžืช ื‘ืฆืขื“ื™ื ืคืฉื•ื˜ื™ื, ืื‘ืœ ื‘ืฉืœ ื”ืขื•ื‘ื“ื” ืฉืžืืžืจื™ื ืขืœ ื–ื” ืžืคื•ื–ืจื™ื ื‘ืจื—ื‘ื™ ื”ืื™ื ื˜ืจื ื˜, ืื™ืŸ ืžื“ืจื™ืš ื”ื•ืจืื•ืช ืฉืœื ืฉื™ื›ืœื•ืœ ืืช ื›ืœ ื”ืฉืœื‘ื™ื ืžืชื—ื™ืœืชื• ื•ืขื“ ืกื•ืคื• (ื™ืฉ ื›ืžื” ืคื•ืกื˜ื™ื ืขืœ Habrรฉ, ืื‘ืœ ื”ืจื‘ื” ื ืงื•ื“ื•ืช ืžื—ืžื™ืฆื•ืช ืฉื).

WAL-G: ื’ื™ื‘ื•ื™ื™ื ื•ืฉื—ื–ื•ืจ ืฉืœ PostgreSQL DBMS

ืžืืžืจ ื–ื” ื ื›ืชื‘ ื‘ืขื™ืงืจ ื›ื“ื™ ืœืกื“ืจ ืืช ื”ื™ื“ืข ืฉืœื™. ืื ื™ ืœื DBA ื•ืื ื™ ื™ื›ื•ืœ ืœื”ืชื‘ื˜ื ื‘ืฉืคืช ื”ื“ื™ื•ื˜ื•ืช ืื™ืคืฉื”ื•, ืื– ื›ืœ ืชื™ืงื•ืŸ ื™ืชืงื‘ืœ ื‘ื‘ืจื›ื”!

ื‘ื ืคืจื“, ืื ื™ ืžืฆื™ื™ืŸ ืฉื›ืœ ืžื” ืœืžื˜ื” ืจืœื•ื•ื ื˜ื™ ื•ื ื‘ื“ืง ืขื‘ื•ืจ PostgreSQL 12.3 ื‘-Ubuntu 18.04, ื›ืœ ื”ืคืงื•ื“ื•ืช ื—ื™ื™ื‘ื•ืช ืœื”ืชื‘ืฆืข ื›ืžืฉืชืžืฉ ืžื™ื•ื—ืก.

ื”ืชืงื ื”

ื‘ื–ืžืŸ ื›ืชื™ื‘ืช ืžืืžืจ ื–ื”, ื”ื’ืจืกื” ื”ื™ืฆื™ื‘ื” ืฉืœ WAL-G ื”ื™ื v0.2.15 (ืžืจืฅ 2020). ื–ื” ืžื” ืฉื ืฉืชืžืฉ (ืื‘ืœ ืื ืืชื” ืจื•ืฆื” ืœื‘ื ื•ืช ืื•ืชื• ื‘ืขืฆืžืš ืžื”ืขื ืฃ ื”ืจืืฉื™, ืื– ืœืžืื’ืจ github ื™ืฉ ืืช ื›ืœ ื”ื”ื•ืจืื•ืช ืœื›ืš). ื›ื“ื™ ืœื”ื•ืจื™ื“ ื•ืœื”ืชืงื™ืŸ ืืชื” ืฆืจื™ืš ืœืขืฉื•ืช:

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

ืœืื—ืจ ืžื›ืŸ, ืขืœื™ืš ืœื”ื’ื“ื™ืจ ืชื—ื™ืœื” ืืช WAL-G, ื•ืœืื—ืจ ืžื›ืŸ ืืช PostgreSQL ืขืฆืžื•.

ื”ื’ื“ืจืช WAL-G

ืœื“ื•ื’ืžื ืฉืœ ืื—ืกื•ืŸ ื’ื™ื‘ื•ื™ื™ื, ืืžื–ื•ืŸ S3 ื™ืฉืžืฉ (ื›ื™ ื”ื•ื ืงืจื•ื‘ ื™ื•ืชืจ ืœืฉืจืชื™ื ืฉืœื™ ื•ื”ืฉื™ืžื•ืฉ ื‘ื• ื–ื•ืœ ืžืื•ื“). ื›ื“ื™ ืœืขื‘ื•ื“ ืื™ืชื•, ืืชื” ืฆืจื™ืš "ื“ืœื™ s3" ื•ืžืคืชื—ื•ืช ื’ื™ืฉื”.

ื›ืœ ื”ืžืืžืจื™ื ื”ืงื•ื“ืžื™ื ืขืœ WAL-G ื”ืฉืชืžืฉื• ื‘ืชืฆื•ืจื” ื‘ืืžืฆืขื•ืช ืžืฉืชื ื™ ืกื‘ื™ื‘ื”, ืืš ืขื ืžื”ื“ื•ืจื” ื–ื• ื ื™ืชืŸ ืœืืชืจ ืืช ื”ื”ื’ื“ืจื•ืช ื‘ ืงื•ื‘ืฅ .walg.json ื‘ืกืคืจื™ื™ืช ื”ื‘ื™ืช ืฉืœ ืžืฉืชืžืฉ postgres. ื›ื“ื™ ืœื™ืฆื•ืจ ืื•ืชื•, ื”ืคืขืœ ืืช ืกืงืจื™ืคื˜ ื”-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

ื”ืจืฉื• ืœื™ ืœื”ืกื‘ื™ืจ ืžืขื˜ ืขืœ ื›ืœ ื”ืคืจืžื˜ืจื™ื:

  • WALG_S3_PREFIX - ื”ื ืชื™ื‘ ืœื“ืœื™ S3 ืฉืœืš ืฉื‘ื• ื™ื•ืขืœื• ื’ื™ื‘ื•ื™ื™ื (ืืชื” ื™ื›ื•ืœ ืœืฉื•ืจืฉ ืื• ืœืชื™ืงื™ื”);
  • AWS_ACCESS_KEY_ID - ืžืคืชื— ื’ื™ืฉื” ื‘-S3 (ื‘ืžืงืจื” ืฉืœ ื”ืชืื•ืฉืฉื•ืช ื‘ืฉืจืช ื‘ื“ื™ืงื”, ืœืžืคืชื—ื•ืช ืืœื” ื—ื™ื™ื‘ ืœื”ื™ื•ืช ืžื“ื™ื ื™ื•ืช ืงืจื™ืื” ื‘ืœื‘ื“! ื–ื” ืžืชื•ืืจ ื‘ื™ืชืจ ืคื™ืจื•ื˜ ื‘ืกืขื™ืฃ ืขืœ ื”ืชืื•ืฉืฉื•ืช.);
  • AWS_SECRET_ACCESS_KEY - ืžืคืชื— ืกื•ื“ื™ ื‘ืื—ืกื•ืŸ S3;
  • WALG_COMPRESSION_METHOD โ€“ ืฉื™ื˜ืช ื“ื—ื™ืกื”, ืขื“ื™ืฃ ืœื”ืฉืชืžืฉ ื‘ื‘ืจื•ื˜ืœื™ (ืžื›ื™ื•ื•ืŸ ืฉื–ื”ื• ื”ืืžืฆืขื™ ื”ืžื•ื–ื”ื‘ ื‘ื™ืŸ ื”ื’ื•ื“ืœ ื”ืกื•ืคื™ ืœืžื”ื™ืจื•ืช ื”ื“ื—ื™ืกื”/ืคื™ืจื•ืง);
  • WALG_DELTA_MAX_STEPS - ืžืกืคืจ ื”"deltas" ืœืคื ื™ ื™ืฆื™ืจืช ื’ื™ื‘ื•ื™ ืžืœื (ื”ื ื—ื•ืกื›ื™ื ื–ืžืŸ ื•ื’ื•ื“ืœ ื”ื ืชื•ื ื™ื ืฉื”ื•ืจื“ื•, ืืš ื™ื›ื•ืœื™ื ืœื”ืื˜ ืžืขื˜ ืืช ืชื”ืœื™ืš ื”ืฉื—ื–ื•ืจ, ื•ืœื›ืŸ ืœื ืžื•ืžืœืฅ ืœื”ืฉืชืžืฉ ื‘ืขืจื›ื™ื ื’ื“ื•ืœื™ื);
  • PGDATA - ื ืชื™ื‘ ืœืกืคืจื™ื™ื” ืขื ื ืชื•ื ื™ ืžืกื“ ื”ื ืชื•ื ื™ื ืฉืœืš (ืืชื” ื™ื›ื•ืœ ืœื’ืœื•ืช ื–ืืช ืขืœ ื™ื“ื™ ื”ืคืขืœืช ื”ืคืงื•ื“ื” pg_lsclusters);
  • PGHOST โ€“ ื”ืชื—ื‘ืจื•ืช ืœืžืกื“ ื”ื ืชื•ื ื™ื, ืขื ื’ื™ื‘ื•ื™ ืžืงื•ืžื™ ืขื“ื™ืฃ ืœืขืฉื•ืช ื–ืืช ื“ืจืš ืฉืงืข ื™ื•ื ื™ืงืก ื›ืžื• ื‘ื“ื•ื’ืžื” ื–ื•.

ื ื™ืชืŸ ืœืžืฆื•ื ืคืจืžื˜ืจื™ื ื ื•ืกืคื™ื ื‘ืชื™ืขื•ื“: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

ื”ื’ื“ืจืช PostgreSQL

ืขืœ ืžื ืช ืฉื”ืืจื›ื™ื•ืŸ ื‘ืชื•ืš ืžืกื“ ื”ื ืชื•ื ื™ื ื™ืขืœื” ืœื•ื’ื™ WAL ืœืขื ืŸ ื•ื™ืฉื—ื–ืจ ืื•ืชื ืžื”ื (ื‘ืžื™ื“ืช ื”ืฆื•ืจืš), ืฆืจื™ืš ืœื”ื’ื“ื™ืจ ืžืกืคืจ ืคืจืžื˜ืจื™ื ื‘ืงื•ื‘ืฅ ื”ืชืฆื•ืจื” /etc/postgresql/12/main/postgresql.conf. ืจืง ื‘ืชื•ืจ ื”ืชื—ืœื” ืืชื” ืฆืจื™ืš ืœื•ื•ื“ืืฉืืฃ ืื—ืช ืžื”ื”ื’ื“ืจื•ืช ืฉืœื”ืœืŸ ืื™ื ื” ืžื•ื’ื“ืจืช ืœืขืจื›ื™ื ืื—ืจื™ื, ื›ืš ืฉื›ืืฉืจ ื”ืชืฆื•ืจื” ื ื˜ืขื ืช ืžื—ื“ืฉ, ื”-DBMS ืื™ื ื• ืงื•ืจืก. ืืชื” ื™ื›ื•ืœ ืœื”ื•ืกื™ืฃ ืคืจืžื˜ืจื™ื ืืœื” ื‘ืืžืฆืขื•ืช:

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

ืชื™ืื•ืจ ื”ืคืจืžื˜ืจื™ื ืฉื™ืฉ ืœื”ื’ื“ื™ืจ:

  • ื•ื•ืœ_ืจืžื” - ื›ืžื” ืžื™ื“ืข ืœื›ืชื•ื‘ ื‘ื™ื•ืžื ื™ WAL, "ืจืคืœื™ืงื”" - ืœื›ืชื•ื‘ ื”ื›ืœ;
  • ืžืฆื‘_ืืจื›ื™ื•ืŸ - ืืคืฉืจ ื”ื•ืจื“ื” ืฉืœ ื™ื•ืžื ื™ WAL ื‘ืืžืฆืขื•ืช ื”ืคืงื•ื“ื” ืžื”ืคืจืžื˜ืจ ืคืงื•ื“ื”_ืืจื›ื™ื•ืŸ;
  • ืคืงื•ื“ื”_ืืจื›ื™ื•ืŸ - ืคืงื•ื“ื” ืœืืจื›ื™ื•ืŸ ื™ื•ืžืŸ WAL ืฉื”ื•ืฉืœื;
  • ืคืกืง ื–ืžืŸ_ืืจื›ื™ื•ืŸ โ€“ ืืจื›ื™ื•ืŸ ืฉืœ ื™ื•ืžื ื™ื ืžืชื‘ืฆืข ืจืง ื›ืฉื”ื•ื ื”ื•ืฉืœื, ืื‘ืœ ืื ื”ืฉืจืช ืฉืœืš ืžืฉื ื”/ืžื•ืกื™ืฃ ืžืขื˜ ื ืชื•ื ื™ื ืœืžืกื“ ื”ื ืชื•ื ื™ื, ืื– ื”ื’ื™ื•ื ื™ ืœื”ื’ื“ื™ืจ ื›ืืŸ ืžื’ื‘ืœื” ืชื•ืš ืฉื ื™ื•ืช, ื•ืœืื—ืจ ืžื›ืŸ ืคืงื•ื“ืช ื”ืืจื›ื™ื•ืŸ ืชื™ืงืจื ื‘ื›ื•ื— (ืื ื™ ื›ื•ืชื‘ ื‘ืื•ืคืŸ ืื™ื ื˜ื ืกื™ื‘ื™ ืœื‘ืกื™ืก ื”ื ืชื•ื ื™ื ื›ืœ ืฉื ื™ื™ื”, ืื– ื”ื—ืœื˜ืชื™ ืœื ืœื”ื’ื“ื™ืจ ืืช ื”ืคืจืžื˜ืจ ื”ื–ื” ื‘ื™ื™ืฆื•ืจ);
  • restore_command โ€“ ื”ืคืงื•ื“ื” ืœืฉื—ื–ื•ืจ ื™ื•ืžืŸ WAL ืžื’ื™ื‘ื•ื™ ืชืฉืžืฉ ืื "ื”ื’ื™ื‘ื•ื™ ื”ืžืœื" (ื’ื™ื‘ื•ื™ ื”ื‘ืกื™ืก) ื—ืกืจ ืืช ื”ืฉื™ื ื•ื™ื™ื ื”ืื—ืจื•ื ื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื.

ืชื•ื›ืœ ืœืงืจื•ื ืขื•ื“ ืขืœ ื›ืœ ื”ืคืจืžื˜ืจื™ื ื”ืœืœื• ื‘ืชืจื’ื•ื ื”ืชื™ืขื•ื“ ื”ืจืฉืžื™: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

ื”ื’ื“ืจืช ืœื•ื— ื–ืžื ื™ื ืœื’ื™ื‘ื•ื™

ืžื” ืฉื™ื’ื™ื“ื•, ื”ื“ืจืš ื”ื ื•ื—ื” ื‘ื™ื•ืชืจ ืœื”ืคืขื™ืœ ืื•ืชื• ื”ื™ื cron. ื–ื” ืžื” ืฉื ืงื‘ืข ืœื™ืฆื™ืจืช ื’ื™ื‘ื•ื™ื™ื. ื ืชื—ื™ืœ ืขื ื”ืคืงื•ื“ื” ืœื™ืฆื™ืจืช ื’ื™ื‘ื•ื™ ืžืœื: ื‘-wal-g ื–ื”ื• ืืจื’ื•ืžื ื˜ ื”ื”ืฉืงื” ื’ื™ื‘ื•ื™-ื“ื—ื™ืคื”. ืื‘ืœ ืจืืฉื™ืช, ืขื“ื™ืฃ ืœื”ืคืขื™ืœ ืืช ื”ืคืงื•ื“ื” ื”ื–ื• ื‘ืื•ืคืŸ ื™ื“ื ื™ ืžื”ืžืฉืชืžืฉ postgres ื›ื“ื™ ืœื•ื•ื“ื ืฉื”ื›ืœ ื‘ืกื“ืจ (ื•ืื™ืŸ ืฉื’ื™ืื•ืช ื’ื™ืฉื”):

#!/bin/bash

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

ืืจื’ื•ืžื ื˜ื™ ื”ื”ืฉืงื” ืžืฆื™ื™ื ื™ื ืืช ื”ื ืชื™ื‘ ืœืกืคืจื™ื™ืช ื”ื ืชื•ื ื™ื - ืื ื™ ืžื–ื›ื™ืจ ืœืš ืฉืืชื” ื™ื›ื•ืœ ืœื’ืœื•ืช ื–ืืช ืขืœ ื™ื“ื™ ื”ืคืขืœื” pg_lsclusters.

ืื ื”ื›ืœ ื”ืœืš ืœืœื ืฉื’ื™ืื•ืช ื•ื”ื ืชื•ื ื™ื ื ื˜ืขื ื• ืœืื—ืกื•ืŸ S3, ืœืื—ืจ ืžื›ืŸ ืชื•ื›ืœ ืœื”ื’ื“ื™ืจ ื”ืคืขืœื” ืชืงื•ืคืชื™ืช ื‘-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

ื‘ื“ื•ื’ืžื” ื–ื•, ืชื”ืœื™ืš ื”ื’ื™ื‘ื•ื™ ืžืชื—ื™ืœ ื›ืœ ื™ื•ื ื‘ืฉืขื” 4:15 ื‘ื‘ื•ืงืจ.

ืžื—ื™ืงืช ื’ื™ื‘ื•ื™ื™ื ื™ืฉื ื™ื

ืกื‘ื™ืจ ืœื”ื ื™ื—, ืื™ื ืš ืฆืจื™ืš ืœืฉืžื•ืจ ืœื—ืœื•ื˜ื™ืŸ ืืช ื›ืœ ื”ื’ื™ื‘ื•ื™ื™ื ืžืชืงื•ืคืช ื”ืžื–ื•ื–ื•ืื™ืงื•ืŸ, ืื– ื–ื” ื™ื”ื™ื” ืฉื™ืžื•ืฉื™ ืžืขืช ืœืขืช "ืœื ืงื•ืช" ืืช ื”ืื—ืกื•ืŸ ืฉืœืš (ื’ื "ื’ื™ื‘ื•ื™ื™ื ืžืœืื™ื" ื•ื’ื ื™ื•ืžื ื™ WAL). ืื ื• ื ืขืฉื” ื–ืืช ื‘ืืžืฆืขื•ืช ืžืฉื™ืžืช cron:

#!/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 ื™ืจื™ืฅ ืืช ื”ืžืฉื™ืžื” ื”ื–ื• ื›ืœ ื™ื•ื ื‘ืฉืขื” 6:30 ื‘ื‘ื•ืงืจ, ื™ืžื—ืง ื”ื›ืœ (ื’ื™ื‘ื•ื™ื™ื ืžืœืื™ื, deltas ื•-WALs) ืžืœื‘ื“ ืขื•ืชืงื™ื ืฉืœ 10 ื”ื™ืžื™ื ื”ืื—ืจื•ื ื™ื, ืืš ื™ืฉืื™ืจ ืœืคื—ื•ืช ื’ื™ื‘ื•ื™ ืื—ื“ ะดะพ ืชืืจื™ืš ืžื•ื’ื“ืจ ื›ืš ืฉื›ืœ ื ืงื•ื“ื” ืœืื—ืจ ืชืืจื™ื›ื™ื ื ื›ืœืœื• ื‘-PITR.

ืฉื—ื–ื•ืจ ืžื’ื™ื‘ื•ื™

ื–ื” ืœื ืกื•ื“ ืฉื”ืžืคืชื— ืœืžืกื“ ื ืชื•ื ื™ื ื‘ืจื™ื ื”ื•ื ืฉื—ื–ื•ืจ ื•ืื™ืžื•ืช ืชืงื•ืคืชื™ ืฉืœ ืชืงื™ื ื•ืช ื”ื ืชื•ื ื™ื ื‘ืคื ื™ื. ืื ื™ ืื’ื™ื“ ืœืš ื›ื™ืฆื“ ืœืฉื—ื–ืจ ื‘ืืžืฆืขื•ืช WAL-G ื‘ืกืขื™ืฃ ื–ื”, ื•ื ื“ื‘ืจ ืขืœ ื”ืžื—ืื•ืช ืžืื•ื—ืจ ื™ื•ืชืจ.

ื™ืฉ ืœืฆื™ื™ืŸ ื–ืืช ื‘ื ืคืจื“ ืฉื›ื“ื™ ืœืฉื—ื–ืจ ื‘ืกื‘ื™ื‘ืช ื‘ื“ื™ืงื” (ื›ืœ ืžื” ืฉื”ื•ื ืœื ื™ื™ืฆื•ืจ) ืฆืจื™ืš ืœื”ืฉืชืžืฉ ื‘ื—ืฉื‘ื•ืŸ Read Only ื‘-S3 ื›ื“ื™ ืœื ืœื“ืจื•ืก ื‘ื˜ืขื•ืช ื’ื™ื‘ื•ื™ื™ื. ื‘ืžืงืจื” ืฉืœ WAL-G, ืขืœื™ืš ืœื”ื’ื“ื™ืจ ืืช ื”ื–ื›ื•ื™ื•ืช ื”ื‘ืื•ืช ืขื‘ื•ืจ ืžืฉืชืžืฉ S3 ื‘ืžื“ื™ื ื™ื•ืช ืงื‘ื•ืฆืชื™ืช (ื”ืฉืคืขื”: ืืคืฉืจ): s3:GetObject, s3:ListBucket, s3:GetBucketLocation. ื•ื›ืžื•ื‘ืŸ, ืืœ ืชืฉื›ื— ืœื”ื’ื“ื™ืจ archive_mode=ื›ื‘ื•ื™ ื‘ืงื•ื‘ืฅ ื”ื”ื’ื“ืจื•ืช postgresql.conf, ื›ื“ื™ ืฉืžืกื“ ื”ื ืชื•ื ื™ื ืฉืœ ื”ื‘ื“ื™ืงื” ืฉืœืš ืœื ื™ืจืฆื” ืœื’ื‘ื•ืช ื‘ืฉืงื˜.

ื”ืฉื™ืงื•ื ืžืชื‘ืฆืข ื‘ืชื ื•ืขื” ืงืœื” ืฉืœ ื”ื™ื“ ืžื—ื™ืงืช ื›ืœ ื ืชื•ื ื™ PostgreSQL (ื›ื•ืœืœ ืžืฉืชืžืฉื™ื), ืื– ืื ื ื”ื™ื–ื”ืจ ืžืื•ื“ ื‘ืขืช ื”ืคืขืœืช ื”ืคืงื•ื“ื•ืช ื”ื‘ืื•ืช.

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

ืœืžื™ ืฉืจื•ืฆื” ืœื‘ื“ื•ืง ืืช ืชื”ืœื™ืš ื”ืฉื—ื–ื•ืจ, ื”ื•ื›ื ื” ืœืžื˜ื” ื—ืชื™ื›ืช ืงืกื bash ืงื˜ื ื”, ื›ืš ืฉื‘ืžืงืจื” ืฉืœ ื‘ืขื™ื•ืช ื‘ืฉื—ื–ื•ืจ, ื”ืกืงืจื™ืคื˜ ื™ืงืจื•ืก ืขื ืงื•ื“ ื™ืฆื™ืื” ืฉืื™ื ื• ืืคืก. ื‘ื“ื•ื’ืžื” ื–ื•, ืžืชื‘ืฆืขื•ืช 120 ื‘ื“ื™ืงื•ืช ืขื ืคืกืง ื–ืžืŸ ืฉืœ 5 ืฉื ื™ื•ืช (ืกื”"ื› 10 ื“ืงื•ืช ืœืฉื—ื–ื•ืจ) ื›ื“ื™ ืœื’ืœื•ืช ืื ืงื•ื‘ืฅ ื”ืื•ืชื•ืช ื ืžื—ืง (ื–ื” ืื•ืžืจ ืฉื”ืฉื—ื–ื•ืจ ื”ืฆืœื™ื—):

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

ืœืื—ืจ ื”ืชืื•ืฉืฉื•ืช ืžื•ืฆืœื—ืช, ืืœ ืชืฉื›ื— ืœื”ืคืขื™ืœ ืืช ื›ืœ ื”ืชื”ืœื™ื›ื™ื ื‘ื—ื–ืจื” (pgbouncer/monit ื•ื›ื•').

ื‘ื“ื™ืงืช ื ืชื•ื ื™ื ืœืื—ืจ ื”ืฉื—ื–ื•ืจ

ื—ื•ื‘ื” ืœื‘ื“ื•ืง ืืช ืชืงื™ื ื•ืช ื‘ืกื™ืก ื”ื ืชื•ื ื™ื ืœืื—ืจ ื”ืฉื—ื–ื•ืจ, ื›ื“ื™ ืฉืœื ื™ื™ื•ื•ืฆืจ ืžืฆื‘ ืฉืœ ื’ื™ื‘ื•ื™ ืฉื‘ื•ืจ/ืขืงื•ื. ื•ืขื“ื™ืฃ ืœืขืฉื•ืช ื–ืืช ืขื ื›ืœ ืืจื›ื™ื•ืŸ ืฉื ื•ืฆืจ, ืื‘ืœ ืื™ืคื” ื•ืื™ืš ืชืœื•ื™ ืจืง ื‘ื“ืžื™ื•ืŸ ืฉืœืš (ืืชื” ื™ื›ื•ืœ ืœื”ืขืœื•ืช ืฉืจืชื™ื ื‘ื•ื“ื“ื™ื ืขืœ ื‘ืกื™ืก ืฉืขืชื™ ืื• ืœื”ืคืขื™ืœ ืฆ'ืง ื‘-CI). ืื‘ืœ ืœื›ืœ ื”ืคื—ื•ืช, ื™ืฉ ืฆื•ืจืš ืœื‘ื“ื•ืง ืืช ื”ื ืชื•ื ื™ื ื•ื”ืื™ื ื“ืงืกื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื.

ื›ื“ื™ ืœื‘ื“ื•ืง ืืช ื”ื ืชื•ื ื™ื, ืžืกืคื™ืง ืœื”ืจื™ืฅ ืื•ืชื ื“ืจืš dump, ืื‘ืœ ืขื“ื™ืฃ ืฉื‘ื™ืฆื™ืจืช ืžืกื“ ื”ื ืชื•ื ื™ื ืชืคืขื™ืœื• ืกื›ื™ืžื™ ื‘ื“ื™ืงื” (ืกื›ื•ืžื™ ื‘ื“ื™ืงืช ื ืชื•ื ื™ื):

#!/bin/bash

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

ืœื‘ื“ื™ืงืช ืื™ื ื“ืงืกื™ื - ืงื™ื™ื ืžื•ื“ื•ืœ amcheck, ื‘ื•ืื• ื ื™ืงื— ืืช ืฉืื™ืœืชืช ื”-sql ืขื‘ื•ืจื• ืž ื‘ื“ื™ืงื•ืช WAL-G ื•ื‘ื ื” ืกื‘ื™ื‘ ื–ื” ืงืฆืช ื”ื™ื’ื™ื•ืŸ:

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

ืชึดืžืฆื•ึผืช

ื‘ืจืฆื•ื ื™ ืœื”ื‘ื™ืข ืืช ืชื•ื“ืชื™ ืœืื ื“ืจื™ื™ ื‘ื•ืจื•ื“ื™ืŸ ืขืœ ืขื–ืจืชื• ื‘ื”ื›ื ืช ื”ืคืจืกื•ื ื•ืชื•ื“ื” ืžื™ื•ื—ื“ืช ืขืœ ืชืจื•ืžืชื• ืœืคื™ืชื•ื— WAL-G!

ื‘ื›ืš ืžืกืชื™ื™ื ื”ืขืจื” ื–ื•. ืื ื™ ืžืงื•ื•ื” ืฉื”ืฆืœื—ืชื™ ืœื”ืขื‘ื™ืจ ืืช ืงืœื•ืช ื”ื”ืชืงื ื” ื•ืืช ื”ืคื•ื˜ื ืฆื™ืืœ ื”ืขืฆื•ื ืœืฉื™ืžื•ืฉ ื‘ื›ืœื™ ื–ื” ื‘ื—ื‘ืจื” ืฉืœืš. ืฉืžืขืชื™ ื”ืจื‘ื” ืขืœ WAL-G, ืื‘ืœ ืืฃ ืคืขื ืœื ื”ื™ื” ืœื™ ืžืกืคื™ืง ื–ืžืŸ ืœืฉื‘ืช ื•ืœื”ื‘ื™ืŸ ืืช ื–ื”. ื•ืื—ืจื™ ืฉื™ื™ืฉืžืชื™ ืืช ื–ื” ื‘ื‘ื™ืช, ื”ืžืืžืจ ื”ื–ื” ื™ืฆื ืžืžื ื™.

ื‘ื ืคืจื“, ืจืื•ื™ ืœืฆื™ื™ืŸ ืฉ-WAL-G ื™ื›ื•ืœ ืœืขื‘ื•ื“ ื’ื ืขื ื”-DBMS ื”ื‘ื:

  • MySQL / MariaDB;
  • MongoDB;
  • ืงืจืŸ DB;
  • ื•ืื ืœืฉืคื•ื˜ ืœืคื™ ื”ืžืชื—ื™ื™ื‘ื™ื, ืฆืคื•ื™ื™ื ืขื•ื“ ื›ืžื”!

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”