如何备份和恢复 Postgres 数据库
您已将 Django Web 应用程序部署到 Internet。恭喜!现在您遇到了一个有趣的新问题:您的应用程序的数据库中充满了宝贵的“实时”数据,如果您丢失了这些数据,它就会永远消失。如果您的数据库被炸毁或损坏,那么您将需要备份来恢复您的数据。这篇文章将介绍如何备份和恢复 PostgreSQL,这是 Django 最常部署的数据库。
不是每个人都需要备份。如果您的 Django 应用程序只是一个爱好项目,那么丢失所有数据可能没什么大不了的。也就是说,如果您的应用程序是业务的关键部分,那么丢失您的应用程序数据可能实际上意味着业务的终结——人们失去工作并破产。因此,至少在某些时候,您不想丢失所有数据。
好消息是备份和恢复 Postgres 非常简单,您只需要两个命令:pg_dump和pg_restore。如果您使用 MySQL 而不是 Postgres,那么您可以使用mysqldump执行与本文中的说明非常相似的操作。
进行数据库备份
我将假设您已经在某个地方运行了 Postgres 数据库。您需要在可以访问数据库的 Linux 机器上从bashshell 运行以下代码。在此示例中,假设您使用ssh登录到数据库服务器。
首先要做的是设置一些Postgres 特定的环境变量来指定您的目标数据库和登录凭据。这主要是为了我们以后的方便。
# The server Postgres is running on
export PGHOST=localhost
# The port Postgres is listening on
export PGPORT=5432
# The database you want to back up
export PGDATABASE=mydatabase
# The database user you are logging in as
export PGUSER=myusername
# The database user's password
export PGPASSWORD=mypassw0rd
您可以通过运行psql命令列出应用数据库中的所有表来测试这些环境变量。
psql -c "\dt"
# Output:
# List of relations
# Schema | Name | Type | Owner
#--------+---------------+-------+--------
# public | auth_group | table | myusername
# public | auth_group... | table | myusername
# public | auth_permi... | table | myusername
# public | django_adm... | table | myusername
# .. etc ..
如果缺少psql,您可以使用apt在 Ubuntu 或 Debian 上安装它:
sudo apt install postgresql-client
现在我们准备使用pg_dump创建数据库转储。使用起来非常简单,因为我们之前设置了这些环境变量。当你运行pg_dump时,它只是将一堆 SQL 语句作为数百甚至数千行文本吐出。您可以使用head查看输出以查看前 10 行文本:
pg_dump | head
# Output:
# --
# -- PostgreSQL database dump
# --
# -- Dumped from database version 9.5.19
# -- Dumped by pg_dump version 9.5.19
# SET statement_timeout = 0;
# SET lock_timeout = 0;
# SET client_encoding = 'UTF8';
pg_dump生成的 SQL 语句是关于如何重新创建数据库的说明。您可以通过将所有这些 SQL 文本写入文件来将此输出转换为备份:
pg_dump > mybackup.sql
而已!您现在有一个数据库备份。您可能已经注意到,将所有数据存储为 SQL 语句是相当低效的。您可以使用“自定义”转储格式压缩此数据:
pg_dump --format=custom > mybackup.pgdump
这种“自定义”格式的文件大小要小约 3 倍,但它对于人类阅读来说并不那么美观,因为它现在采用了一些时髦的非文本二进制格式:
pg_dump --format=custom | head
# Output:
# xtshirt9.5.199.5.19k0ENCODINENCODING
# SET client_encoding = 'UTF8';
# false00
# ... etc ...
最后,mybackup.pgdump是一个糟糕的文件名。目前尚不清楚文件中的内容。我们会记住这是用于哪个数据库吗?我们怎么知道这是最新鲜的副本?让我们添加一个时间戳加上一个描述性名称来帮助我们记住:
# Get Unix epoch timestamp
# Eg. 1591255548
TIME=$(date "+%s")
# Descriptive file name
# Eg. postgres_mydatabase_1591255548.pgdump
BACKUP_FILE="postgres_${PGDATABASE}_${TIME}.pgdump"
pg_dump --format=custom > $BACKUP_FILE
现在,您可以每月、每周或每天运行这些命令来获取数据的快照。如果你愿意,你可以把整个事情写成一个名为backup.sh的bash脚本:
#!/bin/bash
# Backs up mydatabase to a file.
export PGHOST=localhost
export PGPORT=5432
export PGDATABASE=mydatabase
export PGUSER=myusername
export PGPASSWORD=mypassw0rd
TIME=$(date "+%s")
BACKUP_FILE="postgres_${PGDATABASE}_${TIME}.pgdump"
echo "Backing up $PGDATABASE to $BACKUP_FILE"
pg_dump --format=custom > $BACKUP_FILE
echo "Backup completed"
您应该避免像我在上面所做的那样对密码进行硬编码,最好将凭据作为脚本参数或环境变量传递。文件/etc/environment是在安全服务器上存储此类凭据的好地方。
从备份中恢复数据库
如果您不知道如何使用它们来恢复数据,那么创建备份是没有意义的。我可以想到三种情况,您想在哪里运行还原:
-
您需要从头开始设置数据库
-
您想将现有数据库回滚到以前的时间
-
你想在你的开发环境中恢复数据
我将一次一个地讨论这些场景。
从头开始恢复
有时您可能会丢失数据库服务器并且什么都没有。也许您不小心删除了它,认为它是不同的服务器。幸运的是你有你的数据库备份文件,并希望有一些自动配置管理可以帮助你快速重新设置服务器。
配置好新服务器并安装 PostgreSQL 后,您需要重新创建数据库和拥有它的用户:
sudo -u postgres psql <<-EOF
CREATE USER $PGUSER WITH PASSWORD '$PGPASSWORD';
CREATE DATABASE $PGDATABASE WITH OWNER $PGUSER;
EOF
然后您可以设置与我们之前所做的相同的环境变量(PGHOST 等),然后使用pg_restore来恢复您的数据。
您可能会看到一些警告错误,这是正常的。
BACKUP_FILE=postgres_mydatabase_1591255548.pgdump
pg_restore --dbname $PGDATABASE $BACKUP_FILE
# Output:
# ... lots of errors ...
# pg_restore: WARNING: no privileges were granted for "public"
# WARNING: errors ignored on restore: 1
我不是 100% 了解所有这些错误的含义,但我相信它们主要与尝试修改用户无权修改的 Postgres 对象的还原脚本有关。如果您使用的是标准 Django 应用程序,这应该不是问题。您可以通过使用psql检查表来检查恢复是否实际工作:
# Check the tables
psql -c "\dt"
# Output:
# List of relations
# Schema | Name | Type | Owner
#--------+---------------+-------+--------
# public | auth_group | table | myusername
# public | auth_group... | table | myusername
# public | auth_permi... | table | myusername
# public | django_adm... | table | myusername
# .. etc ..
# Check the last migration
psql -c "SELECT * FROM django_migrations ORDER BY id DESC LIMIT 1"
# Output:
# id | app | name | applied
# ----+--------+-----------+---------------
# 20 | tshirt | 0003_a... | 2019-08-26...
给你!您的数据库已恢复。危机化解了。
回滚现有数据库
如果要将现有数据库回滚到以前的时间点,删除所有新数据,则需要使用--clean标志,该标志会在重新创建之前删除恢复的数据库表(此处为文档):
BACKUP_FILE=postgres_mydatabase_1591255548.pgdump
pg_restore --clean --dbname $PGDATABASE $BACKUP_FILE
恢复开发环境
从已知备份恢复测试或开发数据库通常是有益的。
执行此操作时,您不必担心设置正确的用户权限。
在这种情况下,您希望完全销毁并重新创建数据库以获得全新的开始,并且您希望使用--no-owner标志来忽略还原脚本中的任何与数据库用户相关的内容:
sudo -u postgres psql -c "DROP DATABASE $PGDATABASE"
sudo -u postgres psql -c "CREATE DATABASE $PGDATABASE"
BACKUP_FILE=postgres_mydatabase_1591255548.pgdump
pg_restore --no-owner --dbname $PGDATABASE $BACKUP_FILE
我经常使用这种方法从生产环境中提取非敏感数据,以尝试重现 prod 中出现的错误。当您有定期数据库备份、错误报告和集中日志记录时,修复神秘错误要容易得多。
后续步骤
我希望您现在拥有备份和恢复 Django 应用程序的 Postgres 数据库所需的工具。如果您想阅读更多Postgres 文档有一个很好的部分数据库备份。
一旦您了解了数据库备份,您应该自动化该过程以使其更可靠。我将在这个后续帖子中向您展示如何做到这一点。
更多推荐
所有评论(0)