如何在 RDS 实例中复制 PostgreSQL RDS 数据库

How to copy a PostgreSQL RDS database within an RDS instance

我在做这件事时遇到了很多麻烦 - 我想我会在 Whosebug 上做一个 Q/A 来解释这个过程。

问题是关于复制 RDS postgres 数据库以供开发使用 - 特别是用于测试数据库迁移脚本等。这就是为什么要关注 "single database" 中的 "single schema"。

就我而言,我想创建一个尽可能独立的测试数据库,同时保留在单个 RDS 实例中(因为旋转整个 RDS 实例需要 5 到 15 分钟,而且我很便宜) .

这是仅使用命令行的答案。

先决条件:

  • 您必须安装 Postgres 客户端工具(不需要实际的服务器)
    • 客户端版本必须与您的 postgres 服务器版本相同或更高
  • 对 RDS 实例的网络访问
  • 用于访问相关数据库帐户的凭据

示例上下文:

  • 我在 rds.example.com 有一个 RDS 实例,它有一个名为 rds_master 的主用户。
  • 我有一个名为 db_dev_user 的“应用程序用户”,一个名为 dev_db 的数据库,其中包含架构 app_schema
  • 注意 postgres 中的“用户”和“角色”是同义词

pg_dump 打印出原始数据库的模式和数据,并且 工作,即使有活动连接到数据库。当然,这些连接的性能可能会受到影响,但数据库 的结果副本是 transactional.

pg_dump --host=rds.example.com --port=5432 \
  --format=custom \
  --username=db_dev_user --dbname=dev_db \
  > pgdumped

createuser命令创建你的测试application/processes应该连接的用户(为了更好的隔离),注意创建的用户不是超级用户,它不能创建数据库或角色。

createuser --host=rds.example.com --port=5432 \
  --username=rds_master \
  --no-createdb --no-createrole --no-superuser \
  --login --pwprompt \
  db_test_user

如果没有下一个 grant 命令,以下 createdb 将失败:

psql --host=rds.example.com --port=5432 \
  --username=rds_master --dbname=postgres \
  --command="grant db_test_user TO rds_master"

createdb 言出必行;请注意,db_test_user 角色“拥有”数据库。

createdb --host=rds.example.com --port=5432 \
  --username=rds_master --owner=db_test_user test_db

接下来是 创建模式 命令。 db_test_user 无法创建模式,但它必须获得模式授权,否则 pg_restore 将失败,因为它最终会尝试恢复到 pg_catalog 模式(因此请注意 user=rds_master, 但 dbname=test_db).

psql --host=rds.example.com --port=5432 \
  --username=rds_master --dbname=test_db \
  --command="create schema app_schema authorization db_test_user"

最后,我们发出pg_restore命令:

pg_restore --host=rds.example.com --port=5432 \
  --verbose --exit-on-error --single-transaction \
  --username=db_test_user --schema=app_schema \
  --dbname=test_db --no-owner \
  ./pgdumped
  • exit-on-error - 因为否则找出问题所在涉及过多的滚动和扫描(这也是 single-transaction 所暗示的)
  • single-transaction - 避免在出现问题时不得不删除或重新创建数据库
  • schema - 只执行我们关心的模式(也可以将其提供给原始 pg_dump 命令)
  • dbname - 确保使用我们创建的数据库
  • no-owner - 我们以 db_test_user 的身份连接,所以一切都应该归正确的用户所有

对于生产,您最好只拍摄实例的 RDS 快照并恢复它,这将创建一个全新的 RDS 实例。

在一个几乎是空的数据库上——创建快照需要几分钟时间,创建新的 RDS 实例需要另外 5 分钟左右(这就是为什么在开发过程中很痛苦的部分原因)。

仅当 运行 时,您才需要为新的 RDS 实例付费。保持在免费层内是我想为开发目的使用相同实例创建此数据库的原因之一,而且不必处理第二个 DNS 名称;当您开始拥有多个环境时,这种效果会成倍增加。

运行 第二个 RDS 实例是更好的生产选择,因为您几乎完全消除了对原始数据库的任何风险。此外,当您处理大量数据时 - snapshot/DB 创建时间与花费 reading/writing 数据的时间相比相形见绌。对于大量数据,Amazon RDS 快照 creation/restore 进程可能比某处单个服务器上的一组脚本 运行 具有更好的并行化。此外,RDS 控制台让您可以看到恢复的进度 - 随着数据集变得越来越大,参与的人越来越多,这将变得非常宝贵。