2012-04-11 46 views
9

我正在寻找一个基本脚本/命令来创建活动数据库的副本(在同一台服务器上,我们将它们命名为mydbmydb_test)。如何从生产中一步一步克隆测试数据库?

要求

  • 它即使mydb_test已经存在运行,并有记录
  • 它的工作即使mydbmydb_test确实有存在的连接
  • 它具有清洁可能存在的数据库如有需要

提示:

  • drop database不能,如果你有现有连接

回答

2

这就是我一直在寻找,但我不得不编译它自己:P

我只希望我知道一种方法来保持相同的用户,并没有把它在脚本中。


#!/bin/bash 
DB_SRC=conf 
DB_DST=conf_test 
DB_OWNER=confuser 

T="$(date +%s)" 

psql -c "select pg_terminate_backend(procpid) from pg_stat_activity where datname='$DB_DST';" || { echo "disconnect users failed"; exit 1; } 
psql -c "drop database if exists $DB_DST;" || { echo "drop failed"; exit 1; } 
psql -c "create database $DB_DST owner confuser;" || { echo "create failed"; exit 1; } 
pg_dump $DB_SRC|psql $DB_DST || { echo "dump/restore failed"; exit 1; } 

T="$(($(date +%s)-T))" 
echo "Time in seconds: ${T}" 
2

既然你不说这是在数据库中下降对象一个问题时,我觉得跟--clean选项运行pg_dump会做什么你想。您可以将pg_dump的输出传输到psql中,以实现这种功能。

5

创建现有(活的)数据库的完整副本,最简单和最快的方法是使用CREATE DATABASE with a TEMPLATE

CREATE DATABASE mydb_test TEMPLATE mydb; 

然而,有一个重要的限制侵犯了您的第二个要求:模板(源)数据库不能有其他连接。 I quote the manual:

它可以创建额外的模板数据库,事实上一个 可以通过指定名称为 模板CREATE DATABASE集群中的复制任何数据库。然而,重要的是要了解 这不是(还)作为通用目的“COPY DATABASE” 设施。主要限制是,在复制源数据库时,不会有其他会话连接到源数据库。 CREATE DATABASE 如果在启动时存在任何其他连接,将会失败;在 复制操作期间,阻止了到源数据库的新连接。

如果您拥有pg_terminate_backend()的必要权限,您可以终止模板数据库的所有会话。
要避免终止会话与从模板复制之间的重新连接,您可以使用revoke the CONNECT privilege (and GRANT back later)

REVOKE CONNECT ON DATABASE mydb FROM PUBLIC; 

-- while connected to another DB (like the default maintenance DB "postgres") 
SELECT pg_terminate_backend(pid) 
FROM pg_stat_activity 
WHERE datname = 'mydb'   -- name of prospective template db 
AND pid <> pg_backend_pid(); -- don't kill your own session 

CREATE DATABASE mydb_test TEMPLATE mydb; 

GRANT CONNECT ON DATABASE mydb TO PUBLIC; -- only if they had it before 

在之前的版本的Postgres 9.2使用procpid代替pid


如果您不能负担终止并发会话,去与管道pg_dump输出至psql就像已经被其他答案所暗示。