Tạo một bản sao của cơ sở dữ liệu trong PostgreSQL


730

Cách chính xác để sao chép toàn bộ cơ sở dữ liệu (cấu trúc và dữ liệu của nó) sang cơ sở dữ liệu mới trong pgAdmin là gì?

Câu trả lời:


1121

Postgres cho phép sử dụng bất kỳ cơ sở dữ liệu hiện có nào trên máy chủ làm mẫu khi tạo cơ sở dữ liệu mới. Tôi không chắc liệu pgAdmin có cung cấp cho bạn tùy chọn trên hộp thoại tạo cơ sở dữ liệu hay không nhưng bạn sẽ có thể thực hiện các thao tác sau trong cửa sổ truy vấn nếu không:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Tuy nhiên, bạn có thể nhận được:

ERROR:  source database "originaldb" is being accessed by other users

Để ngắt kết nối tất cả người dùng khác khỏi cơ sở dữ liệu, bạn có thể sử dụng truy vấn này:

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid();

68
Lưu ý rằng originaldb cần không hoạt động (không có giao dịch ghi) để làm việc này.
synecdoche

62
trong pgAdmin3, trong khung Trình duyệt đối tượng (bên trái), tôi có thể chọn Servers-> (máy chủ của tôi) -> Databases, nhấp chuột phải vào Cơ sở dữ liệu và chọn "Cơ sở dữ liệu mới". Một trong các tùy chọn là mẫu và SQL được sử dụng để tạo cơ sở dữ liệu là tương đương. Nó là rất nhanh hơn nhiều so với một dump / khôi phục trên cùng một máy chủ.
jwhitlock

22
Tôi biết đây là một Q / A cũ, nhưng tôi cảm thấy cần phải làm rõ: Khi @synecdoche nói rằng bản gốcdb phải không hoạt động, điều đó có nghĩa là không có khả năng ghi nào cả. "Sao chép" cơ sở dữ liệu theo kiểu này không khóa gốcdb. PostgreSQL chỉ ngăn bắt đầu sao chép nếu có người khác truy cập vào gốcdb - không phải sau khi bản sao bắt đầu, vì vậy có thể một kết nối khác có thể sửa đổi cơ sở dữ liệu trong khi "bản sao" đang xảy ra. IMHO, đây có thể là câu trả lời dễ nhất, nhưng "tốt nhất" sẽ là sử dụng kết xuất / khôi phục.
Josh

10
Tôi vừa nhìn thấy nó. @Josh: trong khi bản gốcdb đang được sao chép bằng cách tạo cơ sở dữ liệu bằng khuôn mẫu, postgresql không cho phép tạo kết nối mới với nó, vì vậy không có thay đổi nào có thể xảy ra.
ceteras

4
Lưu ý rằng nếu bạn đang sử dụng pgAdmin và thực thi CREATE DATABASE ... TEMPLATE xxx từ cửa sổ lệnh SQL, bạn phải ngắt kết nối với cơ sở dữ liệu trong cửa sổ pgAdmin chính hoặc bạn sẽ gặp lỗi về người dùng được kết nối với cơ sở dữ liệu.
Jack RG

296

Một phiên bản dòng lệnh của câu trả lời của Bell :

createdb -O ownername -T originaldb newdb

Điều này nên được chạy theo các đặc quyền của chủ cơ sở dữ liệu, thường là postgres.


5
Đây là một lệnh hay NHƯNG bạn sẽ nhận được createdb: database creation failed: ERROR: source database "conf" is being accessed by other usersnếu bạn cố gắng thực hiện nó trên cơ sở dữ liệu sản xuất và như mong đợi, bạn không muốn tắt nó để tạo một bản sao.
sorin

7
Có, hãy cẩn thận áp dụng cho lệnh này, như để giải thích rõ ràng lời gọi CREATE DATABASE. Giống như các ý kiến ​​cho câu trả lời của Bell ở trên, cơ sở dữ liệu sẽ không hoạt động.
zbyszek

108

Để sao chép cơ sở dữ liệu hiện có với postgres, bạn có thể làm điều đó

/* 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;

CNTT sẽ giết tất cả các kết nối đến db nguồn để tránh lỗi

ERROR:  source database "SOURCE_DB" is being accessed by other users

7
+1 để đề cập đến giải pháp tập lệnh để tránh lỗi truy cập
bắt nạt

14
Trên Postgres 9.2 Tôi phải thay thế procpidvới pidviệc này đến công việc
marxjohnson

75

Trong môi trường sản xuất, nơi cơ sở dữ liệu gốc đang lưu lượng truy cập, tôi chỉ đơn giản sử dụng:

pg_dump production-db | psql test-db

8
Một vấn đề tôi đã tìm thấy với phương pháp này là pg_dump sẽ giữ giao dịch mở cho đến khi quá trình khôi phục vào cơ sở dữ liệu mới hoàn tất, ngay cả khi pg_dump đã thực sự kết thúc kết xuất của nó. Điều này có thể gây ra sự cố khóa trong một số trường hợp (ví dụ: nếu câu lệnh DDL được chạy trên DB nguồn).
Chris Butler

3
Thêm một cho việc không sử dụng các tập tin trung gian tạm thời.
Ardee Aram

Đó cũng là giải pháp của tôi. Hôm qua nó đã làm việc, bây giờ ràng buộc duy nhất ngẫu nhiên bị vi phạm. Lưu ý: Tôi thả tất cả các bảng để nhận db.
gunzapper


1
Điều này giả định rằng test-db tồn tại. Nếu không, hãy tạo db mới với$ createdb newdb
Samoody

50

Không biết về pgAdmin, nhưng pgdumpcung cấp cho bạn một cơ sở dữ liệu trong SQL. Bạn chỉ cần tạo một cơ sở dữ liệu cùng tên và làm

psql mydatabase < my dump

để khôi phục tất cả các bảng và dữ liệu của chúng và tất cả các đặc quyền truy cập.


Cảm ơn, tôi cần tạo một bãi chứa từ một máy chủ khác và có vẻ như điều này có ích: postgresql.org/docs/8.3/interactive/ chủ
egaga

19
Bạn thậm chí có thể làm được pg_dump -U postgres sourcedb | psql -U postgres newdbmặc dù hiệu quả của kỹ thuật này có thể gây nghi ngờ (vì bạn có thể kết thúc việc chuyển đổi ngữ cảnh giữa đọc và viết)
Frank Farmer

1
Bạn thậm chí có thể nhận được kết xuất của mình từ một máy từ xa thông qua ssh: ssh dbserver pg_dump DBNAME | psql NEWDB... hoặc pg_dump DBNAME | ssh otherserver pgsql NEWDB ... Tất nhiên, quyền và xác thực tất nhiên cần phải được xử lý tuy nhiên bạn muốn xử lý chúng.
ghoti

23

Đầu tiên, sudolà người dùng cơ sở dữ liệu:

sudo su postgres

Chuyển đến dòng lệnh PostgreSQL:

psql

Tạo cơ sở dữ liệu mới, cung cấp quyền và thoát:

CREATE DATABASE new_database_name;
GRANT ALL PRIVILEGES ON DATABASE new_database_name TO my_user;
\d

Sao chép cấu trúc và dữ liệu từ cơ sở dữ liệu cũ sang cơ sở dữ liệu mới:

pg_dump old_database_name | psql new_database_name

Làm thế nào để đảm bảo rằng mọi hoạt động đều ổn ngay cả một số lỗi (sự cố mạng) đã xảy ra? Làm thế nào để kiểm tra xem hai cơ sở dữ liệu có giống nhau sau khi di chuyển không?
BAE

Lỗi nên được hiển thị trong thiết bị đầu cuối bất cứ khi nào gặp phải. Hai cơ sở dữ liệu nên giống nhau sau khi hoạt động. Tuy nhiên, tôi không biết cách kiểm tra điều này ...
Mathieu Rodic

2
Hoạt động như một cơ duyên, tôi đã làm điều đó trong khi cơ sở dữ liệu đang được sản xuất.
BioRod

Điều này dường như hoạt động tốt; tuy nhiên, hai cơ sở dữ liệu có kích thước đĩa khác nhau thông qua \l+. Tại sao kích thước khác nhau?
kosgeinsky

@kosgeinsky điều này đã được trả lời rộng rãi ở đây: dba.stackexchange.com/a/102089/39386
Mathieu Rodic

18

Tôi đã áp dụng phương pháp này cùng với các ví dụ từ trên. Tôi đang làm việc trên một máy chủ "đang tải" và gặp lỗi khi tôi thử cách tiếp cận từ @zbyszek. Tôi cũng đã theo một giải pháp "chỉ dòng lệnh".

createdb: database creation failed: ERROR: source database "exampledb" is being accessed by other users.

Đây là những gì làm việc cho tôi ( Các lệnh được chuẩn bị trước nohupđể di chuyển đầu ra vào một tệp và bảo vệ khỏi ngắt kết nối máy chủ ):

  1. nohup pg_dump exampledb > example-01.sql
  2. createdb -O postgres exampledbclone_01

    người dùng của tôi là "postgres"

  3. nohup psql exampledbclone_01 < example-01.sql


15

Trong pgAdmin, bạn có thể tạo bản sao lưu từ cơ sở dữ liệu gốc của mình, sau đó chỉ cần tạo cơ sở dữ liệu mới và khôi phục từ bản sao lưu vừa tạo:

  1. Nhấp chuột phải vào cơ sở dữ liệu nguồn, Sao lưu ... và kết xuất thành tệp.
  2. Nhấp chuột phải, Đối tượng mới, Cơ sở dữ liệu mới ... và đặt tên đích.
  3. Nhấp chuột phải vào cơ sở dữ liệu mới, Khôi phục ... và chọn tệp của bạn.

Tôi có các bảng liên quan thông qua khóa ngoại và điều này hoạt động tốt.
Randall Blake

12

Cách chính xác để sao chép toàn bộ cơ sở dữ liệu (cấu trúc và dữ liệu của nó) sang cơ sở dữ liệu mới trong pgAdmin là gì?

Câu trả lời:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Đã thử và thử nghiệm.


3
Điều này đòi hỏi gốcdb không được sử dụng. Phương pháp của Isomor không.
Bradley

2
Câu trả lời tương tự đã được cung cấp gần ba năm trước cho bạn
Jason S

8

Từ tài liệu , việc sử dụng createdbhoặc CREATE DATABASEvới các mẫu không được khuyến khích:

Mặc dù có thể sao chép một cơ sở dữ liệu khác với template1 bằng cách chỉ định tên của nó là mẫu, nhưng đây không phải là (chưa) được dự định là một cơ sở đa năng COPY DATABASE. Hạn chế chính là không có phiên nào khác có thể được kết nối với cơ sở dữ liệu mẫu trong khi nó đang được sao chép. CREATE DATABASE sẽ thất bại nếu có bất kỳ kết nối nào khác tồn tại khi nó bắt đầu; mặt khác, các kết nối mới đến cơ sở dữ liệu mẫu sẽ bị khóa cho đến khi CREATE DATABASE hoàn tất.

pg_dumphoặc pg_dumpalllà một cách tốt để sao chép cơ sở dữ liệu VÀ TẤT CẢ DỮ LIỆU. Nếu bạn đang sử dụng GUI như pgAdmin, các lệnh này được gọi phía sau hậu trường khi bạn thực hiện lệnh sao lưu. Sao chép vào cơ sở dữ liệu mới được thực hiện theo hai giai đoạn: Sao lưu và Khôi phục

pg_dumpalllưu tất cả các cơ sở dữ liệu trên cụm PostgreQuery. Nhược điểm của phương pháp này là bạn kết thúc với một tệp văn bản có khả năng rất lớn chứa đầy đủ SQL cần thiết để tạo cơ sở dữ liệu và điền dữ liệu. Ưu điểm của phương pháp này là bạn có được tất cả các vai trò (quyền) cho cụm miễn phí. Để kết xuất tất cả các cơ sở dữ liệu, hãy làm điều này từ tài khoản superuser

pg_dumpall > db.out

và để khôi phục

psql -f db.out postgres

pg_dumpcó một số tùy chọn nén cung cấp cho bạn các tệp nhỏ hơn nhiều. Tôi có một cơ sở dữ liệu sản xuất Tôi sao lưu hai lần một ngày với một công việc định kỳ bằng cách sử dụng

pg_dump --create --format=custom --compress=5 --file=db.dump mydatabase

trong đó compressmức nén (0 đến 9) và createyêu pg_dumpcầu thêm các lệnh để tạo cơ sở dữ liệu. Khôi phục (hoặc di chuyển đến cụm mới) bằng cách sử dụng

pg_restore -d newdb db.dump

trong đó newdb là tên của cơ sở dữ liệu bạn muốn sử dụng.

Những điều khác để suy nghĩ về

PostgreSQL sử dụng VAI TRÒ để quản lý quyền. Chúng không được sao chép bởi pg_dump. Ngoài ra, chúng tôi chưa xử lý các cài đặt trong postgresql.confpg_hba.conf (nếu bạn đang di chuyển cơ sở dữ liệu sang máy chủ khác). Bạn sẽ phải tự mình tìm ra các cài đặt conf. Nhưng có một mẹo tôi vừa phát hiện ra để sao lưu vai trò. Vai trò được quản lý ở cấp độ cụm và bạn có thể yêu cầu pg_dumpallchỉ sao lưu các vai trò bằng công --roles-onlytắc dòng lệnh.


7

PostgreQuery 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;

3
Điều này có thể được thực hiện vì CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;kết quả là yêu cầu cơ sở dữ liệu gốc phải ở chế độ chờ (không có kết nối với quyền truy cập ghi) và bất kỳ kết nối mới nào với cơ sở dữ liệu gốc đều bị ngăn chặn trong khi quá trình sao chép đang được xử lý. Nếu bạn hài lòng với điều đó, điều này sẽ làm việc.
Mikko Rantalainen

Chi tiết đẹp. Cảm ơn bạn!
Arta

6

Đối với những người vẫn quan tâm, tôi đã đưa ra một kịch bản bash thực hiện (ít nhiều) những gì tác giả muốn. Tôi đã phải tạo một bản sao cơ sở dữ liệu kinh doanh hàng ngày trên một hệ thống sản xuất, kịch bản này dường như thực hiện các mẹo. Nhớ thay đổi tên cơ sở dữ liệu / giá trị người dùng / pw.

#!/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"

5

Để tạo kết xuất cơ sở dữ liệu

cd /var/lib/pgsql/
pg_dump database_name> database_name.out

Để thay đổi cơ sở dữ liệu

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

5

Đây là toàn bộ quá trình tạo bản sao qua cơ sở dữ liệu chỉ bằng GUI pgadmin4 (thông qua sao lưu và khôi phục)

Postgres đi kèm với PGadmin4. Nếu bạn sử dụng macOS, bạn có thể nhấn CMD+ SPACEvà gõ pgadmin4để chạy nó. Điều này sẽ mở ra một tab trình duyệt bằng chrome.


Các bước để sao chép

1. Tạo bản sao lưu

Thực hiện việc này bằng cách bấm chuột phải vào cơ sở dữ liệu -> "sao lưu"

nhập mô tả hình ảnh ở đây

2. Đặt tên cho tệp.

Thích test12345. Nhấn vào sao lưu. Điều này tạo ra một kết xuất tệp nhị phân, nó không ở .sqlđịnh dạng

nhập mô tả hình ảnh ở đây

3. Xem nơi nó được tải xuống

Cần có một cửa sổ bật lên ở phía dưới màn hình của bạn. Nhấp vào trang "chi tiết hơn" để xem nơi sao lưu của bạn được tải xuống

nhập mô tả hình ảnh ở đây

4. Tìm vị trí của tệp đã tải xuống

Trong trường hợp này, nó /users/vincenttang

nhập mô tả hình ảnh ở đây

5. Khôi phục bản sao lưu từ pgadmin

Giả sử bạn đã thực hiện đúng các bước từ 1 đến 4, bạn sẽ có tệp nhị phân khôi phục. Sẽ có lúc đồng nghiệp của bạn muốn sử dụng tệp khôi phục của bạn trên máy cục bộ của họ. Đã nói người đi pgadmin và khôi phục

Thực hiện việc này bằng cách bấm chuột phải vào cơ sở dữ liệu -> "khôi phục"

nhập mô tả hình ảnh ở đây

6. Chọn công cụ tìm tập tin

Đảm bảo chọn vị trí tệp theo cách thủ công, KHÔNG kéo và thả tệp vào các trường tải lên trong pgadmin. Bởi vì bạn sẽ chạy vào các quyền lỗi. Thay vào đó, hãy tìm tệp bạn vừa tạo:

nhập mô tả hình ảnh ở đây

7. Tìm tập tin nói

Bạn có thể phải thay đổi bộ lọc ở dưới cùng thành "Tất cả các tệp". Tìm tệp sau đó, từ bước 4. Bây giờ nhấn nút "Chọn" phía dưới để xác nhận

nhập mô tả hình ảnh ở đây

8. Khôi phục tập tin đã nói

Bạn sẽ thấy trang này một lần nữa, với vị trí của tệp được chọn. Đi trước và khôi phục nó

nhập mô tả hình ảnh ở đây

9. Thành công

Nếu tất cả đều tốt, phía dưới bên phải sẽ bật lên một chỉ báo cho thấy khôi phục thành công. Bạn có thể điều hướng đến các bảng của mình để xem liệu dữ liệu đã được khôi phục phù hợp trên mỗi bảng chưa.

10. Nếu nó không thành công:

Nếu bước 9 không thành công, hãy thử xóa lược đồ công khai cũ trên cơ sở dữ liệu của bạn. Chuyển đến "Công cụ truy vấn"

nhập mô tả hình ảnh ở đây

Thực thi khối mã này:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

nhập mô tả hình ảnh ở đây

Bây giờ hãy thử các bước 5 đến 9 một lần nữa, nó sẽ hoạt động

EDIT - Một số ghi chú bổ sung. Cập nhật PGADMIN4 nếu bạn gặp lỗi trong khi tải lên với một cái gì đó dọc theo dòng "tiêu đề lưu trữ 1.14 phiên bản không được hỗ trợ" trong quá trình khôi phục


3

Nếu cơ sở dữ liệu có kết nối mở, tập lệnh này có thể giúp đỡ. Tôi sử dụng điều này để tạo cơ sở dữ liệu thử nghiệm từ bản sao lưu cơ sở dữ liệu sản xuất trực tiếp mỗi đêm. Điều này giả định rằng bạn có một tệp sao lưu .Query từ db sản xuất (tôi thực hiện điều này trong webmin).

#!/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"

1

Sử dụng pgAdmin, ngắt kết nối cơ sở dữ liệu mà bạn muốn sử dụng làm mẫu. Sau đó, bạn chọn nó làm mẫu để tạo cơ sở dữ liệu mới, điều này tránh được lỗi đã sử dụng.


0

Nếu bạn muốn sao chép toàn bộ lược đồ, bạn có thể tạo pg_dump bằng lệnh sau:

pg_dump -h database.host.com -d database_name -n schema_name -U database_user --password

Và khi bạn muốn nhập kết xuất đó, bạn có thể sử dụng:

psql "host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name" -f sql_dump_to_import.sql

Thông tin thêm về chuỗi kết nối: https://www.postgresql.org/docs/civerse/libpq-connect.html#LIBPQ-CONNSTRING

Hoặc sau đó chỉ cần kết hợp nó trong một lớp lót:

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”

0
  1. Mở Cửa sổ chính trong pgAdmin và sau đó mở Cửa sổ công cụ truy vấn khác
  2. Trong các cửa sổ chính trong pgAdmin,

Ngắt kết nối cơ sở dữ liệu "templated" mà bạn muốn sử dụng làm mẫu.

  1. Cửa sổ công cụ truy vấn

Chạy 2 truy vấn như dưới đây

SELECT pg_terminate_backend(pg_stat_activity.pid) 
    FROM pg_stat_activity 
    WHERE pg_stat_activity.datname = 'TemplateDB' AND pid <> pg_backend_pid(); 

(Câu lệnh SQL ở trên sẽ chấm dứt tất cả các phiên hoạt động với TemplateDB và sau đó bạn có thể chọn nó làm mẫu để tạo cơ sở dữ liệu TargetDB mới, điều này tránh được lỗi đã sử dụng.)

CREATE DATABASE 'TargetDB'
  WITH TEMPLATE='TemplateDB'
       CONNECTION LIMIT=-1;

-4

Thử cái này:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.