Creating a copy of a database in PostgreSQL
在pgadmin中,将整个数据库(其结构和数据)复制到新数据库的正确方法是什么?
Postgres允许在创建新数据库时使用服务器上的任何现有数据库作为模板。我不确定pgadmin是否为您提供了"创建数据库"对话框上的选项,但如果没有,您应该能够在查询窗口中执行以下操作:
1 | CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser; |
不过,你可能会得到:
1 | ERROR: SOURCE DATABASE"originaldb" IS being accessed BY other users |
要修复它,可以使用此查询
1 2 | SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid(); |
贝尔答案的命令行版本:
1 | createdb -O ownername -T originaldb newdb |
这应该在数据库主服务器(通常是Postgres)的权限下运行。
要用Postgres克隆现有数据库,可以这样做
1 2 3 4 5 6 | /* KILL ALL EXISTING CONNECTION FROM ORIGINAL DB (sourcedb)*/ SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'SOURCE_DB' AND pid <> pg_backend_pid(); /* CLONE DATABASE TO NEW ONE(TARGET_DB) */ CREATE DATABASE TARGET_DB WITH TEMPLATE SOURCE_DB OWNER USER_DB; |
它将终止与源数据库的所有连接,从而避免出现错误。
1 | ERROR: SOURCE DATABASE"SOURCE_DB" IS being accessed BY other users |
在生产环境中,原始数据库处于流量下,我只是使用:
1 | pg_dump production-db | psql test-db |
不知道pgadmin,但是
1 | psql mydatabase < my dump |
恢复所有表及其数据和所有访问权限。
首先,
1 | sudo su postgres |
转到postgresql命令行:
1 | psql |
创建新数据库,授予权限并退出:
1 2 3 | CREATE DATABASE new_database_name; GRANT ALL PRIVILEGES ON DATABASE new_database_name TO my_user; \d |
将结构和数据从旧数据库复制到新数据库:
1 | pg_dump old_database_name | psql new_database_name |
我将这种方法与上面的例子结合起来。我正在一个"欠载"的服务器上工作,当我尝试从@zbyszek进行访问时出错。我也在寻求"仅限命令行"的解决方案。
以下是我的工作原理(使用
my user is"postgres"
在pgadmin中,您可以从原始数据库进行备份,然后只需创建一个新数据库并从刚刚创建的备份中还原:
在pgadmin中,将整个数据库(其结构和数据)复制到新数据库的正确方法是什么?
答:
1 | CREATE DATABASE newdb WITH TEMPLATE originaldb; |
经过测试。
《PostgreSQL》9.1.2:
1 | $ CREATEDB new_db_name -T orig_db_name -O db_user; |
创建数据库转储
1 2 | cd /var/lib/pgsql/ pg_dump database_name> database_name.out |
重新分配数据库转储
1 2 3 4 5 6 7 8 9 10 11 12 | psql -d template1 CREATE DATABASE database_name WITH ENCODING 'UTF8' LC_CTYPE 'en_US.UTF-8' LC_COLLATE 'en_US.UTF- 8' TEMPLATE template0; CREATE USER role_name WITH PASSWORD 'password'; ALTER DATABASE database_name OWNER TO role_name; ALTER USER role_name CREATEDB; GRANT ALL PRIVILEGES ON DATABASE database_name TO role_name; CTR+D(logout FROM pgsql console) cd /var/lib/pgsql/ psql -d database_name -f database_name.out |
对于那些仍然感兴趣的人,我已经想出了一个bash脚本,它执行(或多或少)作者想要的操作。我不得不每天在生产系统上复制一份商业数据库,这个脚本似乎能做到这一点。请记住更改数据库名称/user/pw值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #!/bin/bash IF [ 1 -ne $# ] THEN echo"Usage `basename $0` {tar.gz database file}" exit 65; fi IF [ -f"$1" ] THEN EXTRACTED=`tar -xzvf $1` echo"using database archive: $EXTRACTED"; ELSE echo"file $1 does not exist" exit 1 fi PGUSER=dbuser PGPASSWORD=dbpw export PGUSER PGPASSWORD datestr=`date +%Y%m%d` dbname="dbcpy_$datestr" createdbcmd="CREATE DATABASE $dbname WITH OWNER = postgres ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8' CONNECTION LIMIT = -1;" dropdbcmp="DROP DATABASE $dbname" echo"creating database $dbname" psql -c"$createdbcmd" rc=$? IF [[ $rc != 0 ]] ; THEN rm -rf"$EXTRACTED" echo"error occured while creating database $dbname ($rc)" exit $rc fi echo"loading data into database" psql $dbname < $EXTRACTED > /dev/NULL rc=$? rm -rf"$EXTRACTED" IF [[ $rc != 0 ]] ; THEN psql -c"$dropdbcmd" echo"error occured while loading data to database $dbname ($rc)" exit $rc fi echo"finished OK" |
如果数据库有打开的连接,此脚本可能会有所帮助。我每天晚上都用它从实时生产数据库的备份中创建一个测试数据库。这假定您有来自生产数据库的.sql备份文件(我在Webmin中这样做)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/bin/sh dbname="desired_db_name_of_test_enviroment" username="user_name" fname="/path to /ExistingBackupFileOfLive.sql" dropdbcmp="DROP DATABASE $dbname" createdbcmd="CREATE DATABASE $dbname WITH OWNER = $username" export PGPASSWORD=MyPassword echo"**********" echo"** Dropping $dbname" psql -d postgres -h localhost -U"$username" -c"$dropdbcmp" echo"**********" echo"** Creating database $dbname" psql -d postgres -h localhost -U"$username" -c"$createdbcmd" echo"**********" echo"** Loading data into database" psql -d postgres -h localhost -U"$username" -d"$dbname" -a -f"$fname" |
在文档中,不鼓励将
Although it is possible to copy a database other than template1 by
specifying its name as the template, this is not (yet) intended as a
general-purpose"COPY DATABASE" facility. The principal limitation is
that no other sessions can be connected to the template database while
it is being copied. CREATE DATABASE will fail if any other connection
exists when it starts; otherwise, new connections to the template
database are locked out until CREATE DATABASE completes.
1 | pg_dumpall > db.out |
并恢复
1 | psql -f db.out postgres |
1 | pg_dump --create --format=custom --compress=5 ==file=db.dump mydatabase |
其中
1 | pg_restore -d newdb db.dump |
其中newdb是要使用的数据库的名称。
其他需要考虑的事情PostgreSQL使用角色来管理权限。这些不是由
使用pgadmin,断开要用作模板的数据库。然后选择它作为创建新数据库的模板,这样可以避免出现已在使用中的错误。
断开要用作模板的"模板化"数据库。
运行2个查询,如下所示
1 2 3 | SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'TemplateDB' AND pid <> pg_backend_pid(); |
(上面的SQL语句将终止所有使用templatedb的活动会话,然后您现在可以选择它作为模板来创建新的targetdb数据库,这避免了获得已在使用的错误。)
1 2 3 | CREATE DATABASE 'TargetDB' WITH TEMPLATE='TemplateDB' CONNECTION LIMIT=-1; |
如果要复制整个架构,可以使用以下命令进行pg_转储:
当您要导入该转储文件时,可以使用:
有关连接字符串的详细信息:https://www.postgresql.org/docs/current/libpq connect.html libpq-connstring
或者只是将其组合在一个行中:
1 | pg_dump -h DATABASE.host.com -d postgres -n schema_name -U database_user --password | psql"host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name" |
试试这个:
1 | CREATE DATABASE newdb WITH ENCODING='UTF8' OWNER=owner TEMPLATE=templatedb LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' CONNECTION LIMIT=-1; |
GL XD