دليل postgresql العملي إدارة النسخ الاحتياطي في قواعد بيانات Postgres


مصطفى عطا العايش

نتعرف في هذا الفصل إلى كيفية أخذ نسخة احتياطية عن قاعدة البيانات الخاصة بنا، ثم نقوم باستعادتها، كما نتعرف إلى الأمر ‎\copy‎ وكيف نستخدمه لتحديد نمط البيانات في النسخة الاحتياطية.

النسخ الاحتياطي والاستعادة

النسخ الاحتياطي هو أخذ نسخة كاملة عن مخططات الجداول وبيانات قاعدة البيانات، أما الاستعادة فهي القدرة على استخدام هذه البيانات التي تم نسخها احتياطيًا وتحميلها إلى قاعدة البيانات الخاصة بك أو قاعدة بيانات اخرى.

ملاحظة: تتم عملية النسخ الاحتياطي والاستعادة على قاعدة بيانات بأكملها أو على جدول بأكمله وليس الهدف منها استخلاص أجزاء من البيانات فقط، ففي تلك الحالة نستخدم النسخ (copy) الذي سنتحدث عنه لاحقًا.

إجراء النسخ الاحتياطي

لأخذ نسخة احتياطية من قاعدة البيانات نستخدم الأداة pg_dump، وعلينا تحديد بعض الإعدادات لتحديد نتيجة عملية النسخ، ومنها:

  • هل نريد أن تكون النتيجة على شكل نص عادي (قابل للقراءة ولكنه كبير الحجم) أو بصيغة ثنائية (غير قابلة للقراءة صغيرة الحجم) أو بصيغة مضغوطة tarball (مثالي للقيام بعملية الاستعادة).
  • هل نرغب بنسخ كل قاعدة البيانات أم مخططات (schema) أو جداول معينة.

قبل البدء بالنسخ الاحتياطي قد ترغب باستعراض قواعد البيانات المخزنة لديك، باستخدام الأمر التالي:

bash-4.2$ psql -l

                                   List of databases
    Name     |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-------------+----------+----------+-------------+-------------+-----------------------
 hsoubguide  | postgres | UTF8     | en_GB.UTF-8 | en_GB.UTF-8 | 
 hsoubguide2 | postgres | UTF8     | en_GB.UTF-8 | en_GB.UTF-8 | 
 postgres    | postgres | UTF8     | en_GB.UTF-8 | en_GB.UTF-8 | 
 template0   | postgres | UTF8     | en_GB.UTF-8 | en_GB.UTF-8 | =c/postgres          +
             |          |          |             |             | postgres=CTc/postgres
 template1   | postgres | UTF8     | en_GB.UTF-8 | en_GB.UTF-8 | =c/postgres          +
             |          |          |             |             | postgres=CTc/postgres
(5 rows)

لاحظ أن العمل يتم ضمن صدفة bash في هذه الفقرة.

يمكنك القيام بعملية النسخ الاحتياطي باستخدام التعليمة التالية:

pg_dump database_name_here > database.sql

فمثلًا سنقوم بأخذ نسخة احتياطية من قاعدة البيانات hsoubguide التي كنا نعمل عليها خلال هذا الدليل كما يلي:

bash-4.2$ pg_dump hsoubguide > /tmp/hsoubguide.sql

خزّنّا نسخة قاعدة البيانات في ملف اسمه hsoubguide.sql ضمن المجلد ‎/‎‎tmp‎، يمكنك مراجعة دليل كيف تفهم هيكلية نظام الملفات في لينكس للتعرف أكثر إلى دور المجلد tmp وغيره في نظام لينكس.

تنتج التعليمة السابقة نسخة عن قاعدة البيانات على شكل نص عادي، سنستعرض أول 50 سطرًا منها من باب الاطلاع:

bash-4.2$ cat /tmp/hsoubguide.sql | head -50

--
-- PostgreSQL database dump
--

-- Dumped from database version 12.3
-- Dumped by pg_dump version 12.3

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 xmloption = content;
SET client_min_messages = warning;
SET row_security = off;

--
-- Name: hstore; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS hstore WITH SCHEMA public;


--
-- Name: EXTENSION hstore; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION hstore IS 'data type for storing sets of (key, value) pairs';


SET default_tablespace = '';

SET default_table_access_method = heap;

--
-- Name: basket_a; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.basket_a (
    id integer NOT NULL,
    fruit character varying(100) NOT NULL
);


ALTER TABLE public.basket_a OWNER TO postgres;

--
-- Name: basket_b; Type: TABLE; Schema: public; Owner: postgres

ولكن بما أن النسخة الاحتياطية مكتوبة بشكلها المقروء، فإن حجمها ليس بالقليل:

bash-4.2$ du -h /tmp/hsoubguide.sql 

212K    /tmp/hsoubguide.sql

بلغ حجم النسخة الاحتياطية 212 كيلو بايت تقريبًا.

لإنشاء نسخة احتياطية أكثر ملاءمة للتخزين الدائم، يمكنك استخدام الضغط لحفظ قاعدة البيانات بشكلها الثنائي

bash-4.2$ pg_dump --format=c hsoubguide > /tmp/hsoubguide.bak

bash-4.2$ du -h /tmp/hsoubguide.bak 
76K    /tmp/hsoubguide.bak

تمكّنّا من ضغط قاعدة البيانات 2.8 مرات تقريبا، وذلك بسبب استخدام الراية format مع الحرف c الذي يدل على الكلمة custome.

للتوسع في استخدام التطبيق pg_dump يمكنك الرجوع إلى توثيق Postgres الرسمي.

استعادة البيانات من نسخة احتياطية

ما رأيك أن نبدأ هذه الفقرة بحركة خطيرة، يمكن أن تؤدي إلى طردك من العمل؟ سنقوم بحذف قاعدة البيانات!

bash-4.2$ dropdb hsoubguide

في حال لم يكن لديك نسخة احتياطية من قاعدة البيانات، فيمكن أن يكون الأمر السابق هو آخر ما تقوم به في عملك، ولكنك قد أخذت نسخة احتياطية بالفعل باستخدام pg_dump في الفقرة السابقة، فلنقم الآن بالاستعادة.

ملاحظة: يجدر بك تعلّم كيفية عمل نسخ احتياطي دوري تلقائي عن طريق مهام cron في لينكس، وقد يفيدك مقال 10 أمثلة لجدولة المهام باستخدام Cron في الأكاديمية.

هناك العديد من الخيارات عند استعادة قاعدة البيانات، ولكن عملية الاستعادة لا يمكنها العمل دون وجود قاعدة بيانات بالفعل ضمن العنقود الخاص بك، لذا عليك إنشاءها ثم الاستعادة إليها كما يلي:

bash-4.2$ createdb hsoubguide
bash-4.2$ pg_restore --format=c --dbname=hsoubguide /tmp/hsoubguide.bak

للتوسع في استخدام التطبيق pg_restore يمكنك الرجوع إلى توثيق Postgres الرسمي.

النسخ (Copy)

يُرفق Postgres بالعديد من الأدوات المساعدة لنقل البيانات أشهرها pg_dump و pg_restore لأخذ نسخة احتياطية من قاعدة البيانات واستعادتها التي تعرفنا عليها في الفقرة السابقة. كما أن هناك أداة مشابهة بنفس القدر من الأهمية إلا أنها أقل شهرة هي أداة Postgres للنسخ التي تسمح بنسخ البيانات من الجداول في قاعدة البيانات وإليها، وتدعم هذه الأداة عدة أنماط، منها:

  • النمط الثنائي
  • نمط الجدولة باستخدام tab
  • نمط csv، للجدولة باستخدام الفاصلة ,

قد تحتاج إلى هذه الأداة يومًا ما سواءً لتحميل كتل من البيانات للتجربة، أو القيام ببعض من عمليات ETL، أو حتى لاستخراج البيانات لإرسالها إلى جهة ما.

أمثلة عملية لاستخدام الأداة Copy

سنبين في هذه الفقرة بعض الأمثلة لشرح طريقة استخدام هذه الأداة، فمثلًا لاستخراج جميع الموظفين إلى ملف مُجدول بواسطة tab:

hsoubguide=# \copy (SELECT * FROM employees) TO '~/employees.tsv';

COPY 5
hsoubguide=# quit
bash-4.2$ ls -l

total 52
drwx------. 4 postgres postgres    51 Jun 15 02:22 12
-rw-rw-r--. 1 postgres postgres    75 Jun 30 06:12 employees.tsv
-rw-r--r--. 1 postgres postgres 46429 Jun  5 16:48 example.dump
bash-4.2$ cat employees.tsv 

1    Jones   45000
2    Adams   50000
3    Johnson 40000
4    Williams    37000
5    Smith   55000

استخراج جميع الموظفين إلى ملف csv:

hsoubguide=# \copy (SELECT * FROM employees) TO '~/employees.csv' WITH (FORMAT CSV); 

COPY 5
hsoubguide=# quit
bash-4.2$ ls -l employees.csv

-rw-rw-r--. 1 postgres postgres 75 Jun 30 06:13 employees.csv
bash-4.2$ cat employees.csv

1,Jones,45000
2,Adams,50000
3,Johnson,40000
4,Williams,37000
5,Smith,55000

استخراج جميع الموظفين إلى ملف ثنائي (لاحظ علامات التنصيص المزدوجة حول الكلمة Binary):

hsoubguide=# \copy (SELECT * FROM employees) TO '~/employees.dat' WITH (FORMAT "binary");

COPY 5
hsoubguide=# quit
bash-4.2$ ls -l employees.dat

-rw-rw-r--. 1 postgres postgres 161 Jun 30 06:16 employees.dat
bash-4.2$ hexdump employees.dat

0000000 4750 4f43 5950 ff0a 0a0d 0000 0000 0000
0000010 0000 0000 0003 0000 0004 0000 0001 0000
0000020 4a05 6e6f 7365 0000 0400 0000 c8af 0300
0000030 0000 0400 0000 0200 0000 0500 6441 6d61
0000040 0073 0000 0004 c300 0050 0003 0000 0004
0000050 0000 0003 0000 4a07 686f 736e 6e6f 0000
0000060 0400 0000 409c 0300 0000 0400 0000 0400
0000070 0000 0800 6957 6c6c 6169 736d 0000 0400
0000080 0000 8890 0300 0000 0400 0000 0500 0000
0000090 0500 6d53 7469 0068 0000 0004 d600 ffd8
00000a0 00ff                                   
00000a1

ولتحميل البيانات من الملفات إلى جدول، فالأسطر التالية تعاكس العمليات السابقة بالترتيب:

\copy employees FROM '~/employees.tsv';
\copy employees FROM '~/employees.csv' WITH CSV;
\copy employees FROM '~/employees.dat' WITH BINARY; 

لتجربة الأوامر السابقة سنقوم بحذف محتويات الجدول واستعادتها كما يلي:

hsoubguide=# DELETE FROM employees;

DELETE 5
hsoubguide=# \copy employees FROM '~/employees.csv' WITH CSV;

COPY 5
hsoubguide=# SELECT * from employees;

 id | last_name | salary 
----+-----------+--------
  1 | Jones     |  45000
  2 | Adams     |  50000
  3 | Johnson   |  40000
  4 | Williams  |  37000
  5 | Smith     |  55000
(5 rows)

إن هذه التعليمة ‎\copy مهمة خصوصًا عند الحاجة إلى إنشاء الجدول خارج صدفة psql عن طريق الكتابة على ملف ما ثم إدخال هذه البيانات مباشرةً إلى جدول في قاعدة البيانات.

ولكن تجدر الإشارة إلى أنه لا يمكن استعادة جدول إلا إذا كان الجدول معرّفًا من قبل في قاعدة البيانات، فكما نرى، فإن البيانات المخزنة في الملفات ليست سوى بيانات الجدول دون تعريف لمخطط الجدول.

خلاصة

إن إدارة النسخ الاحتياطي لقاعدة البيانات أمر شديد الأهمية، ولن يقدّر أحد أهميته كما يقدرها من فقد بياناته دون أخذه مسبقًا لنسخة احتياطية، وقد تعرفنا في هذا الفصل على الأدوات المساعدة على ذلك، فاستخدمها بشكل دوري، ولا تعرض بياناتك لخطر الزوال.

اقرأ أيضًا





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن