Бизнесът и услугите предоставят стойност въз основа на данни. Наличността, постоянното състояние и издръжливостта са основни приоритети за поддържане на удовлетвореност на клиентите и крайните потребители. Загубени или недостъпни данни биха могли да се равняват на изгубени клиенти.
Архивирането на бази данни трябва да бъде в челните редици на ежедневните операции и задачи.
Трябва да сме подготвени за случай, когато данните ни се повредят или загубят.
Твърдо вярвам в една стара поговорка, която съм чувал:„По-добре да го имаш и да не се нуждаеш от него, отколкото да имаш нужда от него и да го нямаш . "
Това важи и за архивиране на база данни. Нека си го кажем, без тях по принцип нямате нищо. Работата с идеята, че нищо не може да се случи с вашите данни, е заблуда.
Повечето СУБД предоставят някои средства за вградени помощни програми за архивиране. PostgreSQL има pg_dump и pg_dumpall от кутията.
И двете предлагат множество опции за персонализиране и структуриране. Покриването на всички тях поотделно в една публикация в блога би било почти невъзможно. Вместо това ще разгледам онези примери, които мога да приложа най-добре, за моето лично развитие/среда за обучение.
Като се има предвид това, тази публикация в блога не е насочена към производствена среда. По-вероятно е най-голяма полза от една работна станция/среда за разработка.
Какво са pg_dump и pg_dumpall?
Документацията описва pg_dump като:„pg_dump е помощна програма за архивиране на PostgreSQL база данни“
И документацията на pg_dumpall:„pg_dumpall е помощна програма за изписване („изхвърляне“) на всички PostgreSQL бази данни на клъстер в един скриптов файл.“
Архивиране на база данни и/или таблица(и)
За да започна, ще създам база данни за практика и някои таблици, с които да работя, използвайки следния SQL:
postgres=# CREATE DATABASE example_backups;
CREATE DATABASE
example_backups=# CREATE TABLE students(id INTEGER,
example_backups(# f_name VARCHAR(20),
example_backups(# l_name VARCHAR(20));
CREATE TABLE
example_backups=# CREATE TABLE classes(id INTEGER,
example_backups(# subject VARCHAR(20));
CREATE TABLE
example_backups=# INSERT INTO students(id, f_name, l_name)
example_backups-# VALUES (1, 'John', 'Thorn'), (2, 'Phil', 'Hampt'),
example_backups-# (3, 'Sue', 'Dean'), (4, 'Johnny', 'Rames');
INSERT 0 4
example_backups=# INSERT INTO classes(id, subject)
example_backups-# VALUES (1, 'Math'), (2, 'Science'),
example_backups-# (3, 'Biology');
INSERT 0 3
example_backups=# \dt;
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | classes | table | postgres
public | students | table | postgres
(2 rows)
example_backups=# SELECT * FROM students;
id | f_name | l_name
----+--------+--------
1 | John | Thorn
2 | Phil | Hampt
3 | Sue | Dean
4 | Johnny | Rames
(4 rows)
example_backups=# SELECT * FROM classes;
id | subject
----+---------
1 | Math
2 | Science
3 | Biology
(3 rows)
Базата данни и таблиците са настроени.
За отбелязване:
В много от тези примери ще се възползвам от \! мета-команда, която ви позволява или да пуснете в обвивка (команден ред), или да изпълните каквито и команди на обвивката, които следват.
Само имайте предвид, че в сесия на терминал или команден ред (означена с водещо „$“ в тази публикация в блога), \! мета-командата не трябва да се включва в нито една от командите pg_dump или pg_dumpall. Отново, това е удобна мета-команда в psql.
Архивиране на една таблица
В този първи пример ще изхвърля единствената таблица на учениците:
example_backups=# \! pg_dump -U postgres -t students example_backups > ~/Example_Dumps/students.sql.
Изброявайки съдържанието на директорията, виждаме, че файлът е там:
example_backups=# \! ls -a ~/Example_Dumps
. .. students.sql
Опциите на командния ред за тази отделна команда са:
- -U postgres:посоченото потребителско име
- -t ученици:таблицата за изхвърляне
- example_backups:базата данни
Какво има във файла student.sql?
$ cat students.sql
--
-- PostgreSQL database dump
--
-- Dumped from database version 10.4 (Ubuntu 10.4-2.pgdg16.04+1)
-- Dumped by pg_dump version 10.4 (Ubuntu 10.4-2.pgdg16.04+1)
SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: students; Type: TABLE; Schema: public; Owner: postgres
--
CREATE TABLE public.students (
id integer,
f_name character varying(20),
l_name character varying(20)
);
ALTER TABLE public.students OWNER TO postgres;
--
-- Data for Name: students; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY public.students (id, f_name, l_name) FROM stdin;
1 John Thorn
2 Phil Hampt
3 Sue Dean
4 Johnny Rames
\.
--
-- PostgreSQL database dump complete
Можем да видим, че файлът има необходимите SQL команди за повторно създаване и повторно попълване на ученици в таблицата.
Но дали резервното копие е добро? Надежден и работещ?
Ще го тестваме и ще видим.
example_backups=# DROP TABLE students;
DROP TABLE
example_backups=# \dt;
List of relations
Schema | Name | Type | Owner
--------+---------+-------+----------
public | classes | table | postgres
(1 row)
Няма го.
След това от командния ред прехвърлете запазеното архивно копие в psql:
$ psql -U postgres -W -d example_backups -f ~/Example_Dumps/students.sql
Password for user postgres:
SET
SET
SET
SET
SET
set_config
------------
(1 row)
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
COPY 4
Нека проверим в базата данни:
example_backups=# \dt;
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | classes | table | postgres
public | students | table | postgres
(2 rows)
example_backups=# SELECT * FROM students;
id | f_name | l_name
----+--------+--------
1 | John | Thorn
2 | Phil | Hampt
3 | Sue | Dean
4 | Johnny | Rames
(4 rows)
Таблицата и данните са възстановени.
Архивиране на множество таблици
В следващия пример ще архивираме и двете таблици с помощта на тази команда:
example_backups=# \! pg_dump -U postgres -W -t classes -t students -d example_backups > ~/Example_Dumps/all_tables.sql
Password:
(Забележете, че трябваше да задам парола в тази команда поради опцията -W, където не го направих в първия пример. Повече за това предстои.)
Нека отново да проверим, че файлът е създаден, като изброим съдържанието на директорията:
example_backups=# \! ls -a ~/Example_Dumps
. .. all_tables.sql students.sql
След това пуснете таблиците:
example_backups=# DROP TABLE classes;
DROP TABLE
example_backups=# DROP TABLE students;
DROP TABLE
example_backups=# \dt;
Did not find any relations.
След това възстановете с архивния файл all_tables.sql:
$ psql -U postgres -W -d example_backups -f ~/Example_Dumps/all_tables.sql
Password for user postgres:
SET
SET
SET
SET
SET
set_config
------------
(1 row)
SET
SET
SET
SET
SET
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
COPY 3
COPY 4
example_backups=# \dt;
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | classes | table | postgres
public | students | table | postgres
(2 rows)
И двете таблици са възстановени.
Както можем да видим с pg_dump, можете да архивирате само една или няколко таблици в конкретна база данни.
Архивиране на база данни
Нека сега да видим как да архивираме цялата база данни example_backups с pg_dump.
example_backups=# \! pg_dump -U postgres -W -d example_backups > ~/Example_Dumps/ex_back_db.sql
Password:
example_backups=# \! ls -a ~/Example_Dumps
. .. all_tables.sql ex_back_db.sql students.sql
Файлът ex_back_db.sql е там.
Ще се свържа с базата данни postgres, за да махна базата данни example_backups.
postgres=# DROP DATABASE example_backups;
DROP DATABASE
След това възстановете от командния ред:
$ psql -U postgres -W -d example_backups -f ~/Example_Dumps/ex_back_db.sql
Password for user postgres:
psql: FATAL: database "example_backups" does not exist
Не е там. Защо не? И къде е?
Първо трябва да го създадем.
postgres=# CREATE DATABASE example_backups;
CREATE DATABASE
След това възстановете със същата команда:
$ psql -U postgres -W -d example_backups -f ~/Example_Dumps/ex_back_db.sql
Password for user postgres:
SET
SET
SET
SET
SET
set_config
------------
(1 row)
SET
SET
SET
CREATE EXTENSION
COMMENT
SET
SET
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
COPY 3
COPY 4
postgres=# \c example_backups;
You are now connected to database "example_backups" as user "postgres".
example_backups=# \dt;
List of relations
Schema | Name | Type | Owner
--------+----------+-------+----------
public | classes | table | postgres
public | students | table | postgres
(2 rows)
База данни и всички налични и отчетени таблици.
Можем да избегнем този сценарий да трябва първо да създадем целевата база данни, като включим опцията -C, когато правим архивиране.
example_backups=# \! pg_dump -U postgres -W -C -d example_backups > ~/Example_Dumps/ex_back2_db.sql
Password:
Ще се свържа отново с базата данни postgres и ще пусна базата данни example_backups, за да можем да видим как работи възстановяването сега (Обърнете внимание на тези команди за свързване и DROP, които не са показани за краткост).
След това в командния ред (забележете, че не е включена опция -d dbname):
$ psql -U postgres -W -f ~/Example_Dumps/ex_back2_db.sql
Password for user postgres:
……………..
(And partway through the output...)
CREATE DATABASE
ALTER DATABASE
Password for user postgres:
You are now connected to database "example_backups" as user "postgres".
SET
SET
SET
SET
SET
set_config
------------
(1 row)
SET
SET
SET
CREATE EXTENSION
COMMENT
SET
SET
CREATE TABLE
ALTER TABLE
CREATE TABLE
ALTER TABLE
COPY 3
COPY 4
Използвайки опцията -C, ние получаваме подкана за парола, за да направим връзка, както е посочено в документацията относно флага -C:
„Започнете изхода с команда за създаване на самата база данни и повторно свързване към създадената база данни.“
След това в psql сесията:
postgres=# \c example_backups;
You are now connected to database "example_backups" as user "postgres".
Всичко е възстановено, готово за работа и без необходимост от създаване на целевата база данни преди възстановяването.
pg_dumpall за целия клъстер
Досега сме архивирали една таблица, множество таблици и една база данни.
Но ако искаме повече от това, например архивиране на целия PostgreSQL клъстер, там трябва да използваме pg_dumpall.
И така, какви са някои забележителни разлики между pg_dump и pg_dumpall?
Като за начало, ето едно важно разграничение от документацията:
„Тъй като pg_dumpall чете таблици от всички бази данни, най-вероятно ще трябва да се свържете като суперпотребител на база данни, за да създадете пълен дъмп. Освен това ще ви трябват привилегии на суперпотребител, за да изпълните запазения скрипт, за да можете да добавяте потребители и групи и да създавате бази данни.“
Използвайки командата по-долу, ще архивирам целия си PostgreSQL клъстер и ще го запиша във файла whole_cluster.sql:
$ pg_dumpall -U postgres -W -f ~/Example_Dumps/Cluster_Dumps/entire_cluster.sql
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Password:
Какво, за Бога? Чудите се дали трябваше да въвеждам парола за всяка подкана?
Да, със сигурност. 24 пъти.
Пребройте ги. (Хей, обичам да изследвам и ровя в различни бази данни, докато научавам? Какво мога да кажа?)
Но защо всички подкани?
Първо, след цялата тази упорита работа, pg_dumpall създаде ли архивния файл?
postgres=# \! ls -a ~/Example_Dumps/Cluster_Dumps
. .. entire_cluster.sql
Да, архивният файл е там.
Нека хвърлим малко светлина върху цялата тази „практика на писане “, като погледнете този пасаж от документацията:
„pg_dumpall трябва да се свърже няколко пъти със сървъра на PostgreSQL (веднъж на база данни). Ако използвате удостоверяване с парола, той ще иска парола всеки път.”
Знам какво си мислиш.
Това може да не е идеално или дори осъществимо. Какво ще кажете за процеси, скриптове или cron задачи, които се изпълняват посред нощ?
Някой ще задържи курсора над клавиатурата, чакайки да пише?
Вероятно не.
Една ефективна мярка за предотвратяване на тези повтарящи се подкани за парола е файл ~/.pgpass.
Ето синтаксиса, който файлът ~/.pgpass изисква, за да работи (пример, предоставен от документацията, вижте връзката по-горе):
hostname:port:database:username:password
С файл ~/.pgpass, присъстващ в моята среда за разработка, съдържащ необходимите идентификационни данни за ролята на postgres, мога да пропусна опцията -W (също -w) и да стартирам pg_dumpall без ръчно удостоверяване с паролата:
$ pg_dumpall -U postgres -f ~/Example_Dumps/Cluster_Dumps/entire_cluster2nd.sql
Изброяване на съдържанието на директорията:
postgres=# \! ls -a ~/Example_Dumps/Cluster_Dumps
. .. entire_cluster2nd.sql entire_cluster.sql
Файлът е създаден и няма повтарящи се подкани за парола.
Запазеният файл може да бъде презареден с psql подобно на pg_dump.
Базата данни за свързване също е по-малко критична според този пасаж от документацията:„Не е важно към коя база данни се свързвате тук, тъй като скриптовият файл, създаден от pg_dumpall, ще съдържа съответните команди за създаване и свързване със запазените бази данни.“
Изтеглете Бялата книга днес Управление и автоматизация на PostgreSQL с ClusterControl Научете какво трябва да знаете, за да внедрите, наблюдавате, управлявате и мащабирате PostgreSQLD Изтеглете Бялата книгаpg_dump, pg_dumpall и shell скриптове - удобна комбинация
В този раздел ще видим няколко примера за включване на pg_dump и pg_dumpall в прости шел скриптове.
Бъдете ясни, това не е урок за shell скрипт. Нито пък съм гуру на shell скриптове. Ще дам основно няколко примера, които използвам в моята локална среда за развитие/обучение.
Първо, нека разгледаме прост шел скрипт, който можете да използвате за архивиране на една база данни:
#!/bin/bash
# This script performs a pg_dump, saving the file the specified dir.
# The first arg ($1) is the database user to connect with.
# The second arg ($2) is the database to backup and is included in the file name.
# $(date +"%Y_%m_%d") includes the current system date into the actual file name.
pg_dump -U $1 -W -C -d $2 > ~/PG_dumps/Dump_Scripts/$(date +"%Y_%m_%d")_$2.sql
Както можете да видите, този скрипт приема 2 аргумента:първият е потребителят (или ролята), с който да се свържете за архивиране, докато вторият е името на базата данни, която искате да архивирате.
Забележете опцията -C в командата, за да можем да възстановим, ако базата данни не съществува, без да е необходимо да я създаваме ръчно предварително.
Нека извикаме скрипта с ролята на postgres за базата данни example_backups (Не забравяйте да направите скрипта изпълним с поне chmod +x, преди да извикате за първи път):
$ ~/My_Scripts/pgd.sh postgres example_backups
Password:
И се уверете, че е там:
$ ls -a ~/PG_dumps/Dump_Scripts/
. .. 2018_06_06_example_backups.sql
Възстановяването се извършва с този архивен скрипт, както в предишните примери.
Подобен шел скрипт може да се използва с pg_dumpall за архивиране на целия PostgreSQL клъстер.
Този шел скрипт ще въведе (|) pg_dumpall в gzip, който след това се насочва към определено местоположение на файла:
#!/bin/bash
# This shell script calls pg_dumpall and pipes into the gzip utility, then directs to
# a directory for storage.
# $(date +"%Y_%m_%d") incorporates the current system date into the file name.
pg_dumpall -U postgres | gzip > ~/PG_dumps/Cluster_Dumps/$(date +"%Y_%m_%d")_pg_bck.gz
За разлика от предишния примерен скрипт, този не приема никакви аргументи.
Ще извикам този скрипт от командния ред (няма подкана за парола, тъй като ролята на postgres използва файла ~/.pgpass - вижте раздела по-горе.)
$ ~/My_Scripts/pgalldmp.sh
След като завърша, ще изброя съдържанието на директорията, показващо и размерите на файловете за сравнение между файловете .sql и gz:
postgres=# \! ls -sh ~/PG_dumps/Cluster_Dumps
total 957M
37M 2018_05_22_pg_bck.gz 32M 2018_06_06_pg_bck.gz 445M entire_cluster2nd.sql 445M entire_cluster.sql
Бележка за архивния формат gz от документите:
„Алтернативните архивни файлови формати трябва да се използват с pg_restore за възстановяване на базата данни.“
Резюме
Събрах ключови точки от документацията за pg_dump и pg_dumpall, заедно с моите наблюдения, за да завърша тази публикация в блога:
Забележка:Точките, предоставени от документацията, са в кавички.
- „pg_dump изхвърля само една база данни“
- Форматът на SQL файл в обикновен текст е изходът по подразбиране за pg_dump.
- Ролята се нуждае от привилегията SELECT, за да стартира pg_dump съгласно този ред в документацията:„pg_dump вътрешно изпълнява оператори SELECT. Ако имате проблеми с изпълнението на pg_dump, уверете се, че можете да изберете информация от базата данни, като използвате например psql”
- За да включите необходимата команда DDL CREATE DATABASE и връзка в архивния файл, включете опцията -C.
- -W:Тази опция принуждава pg_dump да поиска парола. Този флаг не е необходим, тъй като ако сървърът изисква парола, все пак ще бъдете подканени. Въпреки това този пасаж в документацията ми привлече окото, така че реших да го включа тук:„Въпреки това, pg_dump ще загуби опит за свързване, за да разбере, че сървърът иска парола. В някои случаи си струва да напишете -W, за да избегнете допълнителния опит за свързване.”
- -d:Посочва базата данни, към която да се свържете. Също в документацията:„Това е еквивалентно на посочване на dbname като първи аргумент без опция в командния ред.“
- Използването на флагове като -t (таблица) позволява на потребителите да архивират части от базата данни, а именно таблици, за които те имат привилегии за достъп.
- Форматите на архивните файлове могат да варират. Въпреки това, .sql файловете са чудесен избор сред другите. Архивните файлове се четат обратно от psql за възстановяване.
- pg_dump може да архивира работеща, активна база данни, без да пречи на други операции (т.е. други четци и записващи).
- Едно предупреждение:pg_dump не изхвърля роли или други обекти на база данни, включително пространства за таблици, а само една база данни.
- За да правите резервни копия на целия си PostgreSQL клъстер, pg_dumpall е по-добрият избор.
- pg_dumpall може да обработва целия клъстер, архивирайки информация за роли, пространства за таблици, потребители, разрешения и т.н., където pg_dump не може.
- Вероятно е, че роля с привилегии SUPERUSER ще трябва да изпълни изхвърлянето и да възстанови/пресъздаде файла, когато бъде прочетен обратно чрез psql, тъй като по време на възстановяването се изисква привилегията за четене на всички таблици във всички бази данни.
Надявам се чрез тази публикация в блога да предоставим подходящи примери и подробности за преглед на ниво начинаещи на pg_dump и pg_dumpall за една среда за разработка/обучение на PostgreSQL.
Въпреки че всички налични опции не бяха проучени, официалната документация съдържа изобилие от информация с примери и за двете помощни програми, така че не забравяйте да се консултирате с този ресурс за допълнително проучване, въпроси и четене.