我正在寻找一个基本脚本/命令,它将创建一个实时数据库的副本(让它们命名为mydb
和mydb_test
,都在同一台服务器上)。
要求
- 即使
mydb_test
已经存在并且有记录,它也必须运行 - 即使
mydb
并且mydb_test
确实有现有的连接,它也必须工作 - 如有必要,它必须清理可能存在的数据库
提示:
drop database
如果您有现有连接,则无法使用
我正在寻找一个基本脚本/命令,它将创建一个实时数据库的副本(让它们命名为mydb
和mydb_test
,都在同一台服务器上)。
要求
mydb_test
已经存在并且有记录,它也必须运行mydb
并且mydb_test
确实有现有的连接,它也必须工作提示:
drop database
如果您有现有连接,则无法使用创建现有(实时)数据库的完整副本的最简单和最快的方法是CREATE DATABASE
使用TEMPLATE
:
CREATE DATABASE mydb_test TEMPLATE mydb;
但是,有一个重要的限制违反了您的第二个要求:模板(源)数据库不能有额外的连接。我引用手册:
可以创建额外的模板数据库,实际上可以通过将其名称指定为
CREATE DATABASE
. 然而,重要的是要理解,这不是(还)打算作为通用的“COPY DATABASE
”设施。主要限制是在复制源数据库时没有其他会话可以连接到源数据库。CREATE DATABASE
如果启动时存在任何其他连接,则会失败;在复制操作期间,将阻止与源数据库的新连接。
如果您拥有必要的权限,则可以终止与模板数据库的所有会话pg_terminate_backend()
。
要暂时禁止重新连接,请撤销CONNECT
特权(GRANT
稍后再撤销)。
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
to psql
like 已经被其他答案所建议。
这就是我一直在寻找的,但我必须自己编译它: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}"
由于您没有说在数据库中删除对象是一个问题,我认为pg_dump
使用该--clean
选项运行将满足您的需求。您可以将 pg_dump 的输出通过管道传输到 psql 中。