
Sqitch ilə məlumat bazaların dəyişiklik menecmenti
İki ay bundan əvvəl F# proqramlaşdırma dili ilə tanış oldum və öyrənməyə başladım. Bir az öyrənən kimi başa düşdüm ki, proqram yazısında mütləq bu dildən istifadə etmək istəyirəm! Bir ay keçəndən sonra yeni layihənin üzərində işləməyə başladım. Əlbətdə ki, onu F#-da yazacağımın qərarına gəldim. Amma bir sualım var idi: məlumat bazası ilə necə işləyəcəyimə əmin deyildim. Təbii ki, mənə artıq tanış olan Entity Framework-u seçə bilərdim, amma o mənim üçün FP-ni unudub OOP-dən istifadə etmək demək idi. Onu mən heç istəməzdim. Həm yazacağım proqram çox kiçik olacaq. Bu kimi, demək olar ki, oyuncaq layihələr üçün Entity Framework həddindən artıq böyük bir alətdir. Mikroskopla mismar vurmaq yaxşı praktika deyil. F# mənə kodu son dərəcədə sadə saxlamağı öyrətdi — alətin dalınca qaçmağı yox. O biri tərəfdən mən məlumat bazasını dəyişiklik menecmentini (change management) etmədən hazırlamaq istəməzdim. Dəyişiklik menecementi bazanı səliqədə saxlamağa və sxemi bir neçə bazaların arasında sinxronlaşdırmağa kömək edir. Entity Framework-un öz miqrasiya alətləri var (Migration API). SQL tip provayderləri isə, kodu sadə saxlamağın imkanını versələr bilə, dəyişiklik menecmenti üçün heç bir alət vermirlər (və verməli deyillər). Bir az fikirləşəndən sonra bazanın dəyişiklik menecmenti üçün back-end-dən ayrı bir proyekt yazacağımın qərarına gəldim. Və onu hansı alətlə idarə edəcəyimi artıq bilirdim.
Sqitch — məlumat bazaları dəyişiklik menecmenti üçün bir alətdir. Sqitch çox yüngül və sadədir, və istifadədə, çoxumuza tanış olan, Git-ə oxşayır. Aydındır ki, Sqitch-dən başqa da alətlər var (düzgün seçim etdiyimə əmin olmaq üçün Google-u yaxşıca axtardım), amma Sqitch mənə artıq tanışdır və bütün ehtiyaclarıma cavab verir. Gəlin bu seçimin Entity Framework-a nisbətən olan mənfi və müsbət cəhətlərinə baxaq:
Müsbət
- Böyük bir freymvorka ehtiyac aradan qaldırılır — nəticədə kod sadələşir və onun sürəti artır
- Bütün proses əlimizdədir, onu istənilən formada qura bilərik
- Dəyişiklik menecmenti proyektini əsas kod bazasını tərpətmədən istənilən yerə (serverə, Docker konteynerinə və s.) köçürtmək olar
- İstənilən miqdarda və istənilən platformalarda (platformaya Sqitch-i yükləmək lazımdır) eyni sxemlə yeni məlumat bazalarını yaratmaq olar
Mənfi
- Əlavə bir alətdən istifadə etməyi öyrənmək lazımdır
- Sqitch Perl-də yazılıb və Perl-də işləyir, ona görə platformaya Perl-i yükləmək lazımdır
- Miqrasiyaları, əsas kod bazasının dilindən fərqli olan, SQL-də yazmaq lazımdır
- Kod generasiyasından yararlana bilmərik
- Əgər bazanı dəyişmək lazım olsa, SQL skriptlərini yeni bazanın ləhcəsinə uyğun dəyişməli olacayıq
Bunun müsbət cəhətləri mənim üçün həqiqətən vacibdirlər. Mənfi cəhətlərinə isə göz yuma bilərəm. Əslində mənim üçün heç birisi çox da vacib deyil. Sqitch-i öyrənmək çox asandır. Perl-i yükləmək də çox çətin deyil, diskdə çox yer tutmur, yükləyəndən sonra isə onu unutmaq olar. SQL də çox asandır, ona görə onu problem hesab etmirəm. Kod generasiyasını ümumiyyətlə xoşlamıram. Az kod yazmağı imkan verən alətləri çox kod generasiya edən alətlərdən üstün tuturam. Proqramın bazası Postgres-də olacaq, ona görə gələcəkdə bazanın dəyişdirilməsi üçün yarana biləcək bir səbəbi heç ağlıma da gətirə bilmirəm, çünki proqram çox balacadır, Postgres isə çox güclü bir RDBMS-dir və həmçinin işdə çox rahatdır. Sqitch bu faktların işığında mənim üçün ideal bir seçimdir.
Test proyektimi Visual Studio Code-da yazacam. Perl-i öz Windows sistemimə də yükləyə bilərdim (Strawberry Perl), amma VS Code-un Remote-SSH əlavəsini istifadə edib uzaq serverdə öz lokal sistemimdə kimi işləyə bilərəm. Ona görə hər şeyi uzaq serverdə edəcəm.
Serverim CentOS 7-dir (başqa sistem üçün Sqitch-in dokumentsiyasına baxa bilərsiniz, linki məqalənin axırına əlavə etdim). İlk növbədə lazım olan proqramları yükləyək. Unutmayın ki, komandaları rutun (root) altında işə salmaq lazımdır:
> yum install git perl-devel perl-CPAN postgresql perl-DBD-Pg
> curl -L https://cpanmin.us | perl - --sudo App::cpanminus
> cpanm --quiet --notest App::SqitchProyekt üçün rutdan başqa adi bir istifadəçi yaratmalıyıq.
> adduser os_userBundan sonra gələcək proyektimiz üçün baza istifadəçısini və bazanın özünü hazırlamalıyıq. Bunun üçün əvvəl postgres istifadəçisinin altında bazaya daxil olmalıyıq. Əgər yeni baza istifadəçisinə OS istifadəçimizin adını versək, PostgreSQL-in Peer Authentication mexanizmindən yararlana biləcəyik. Peer Authentication bizə bazaya psql komandası vasitəsi ilə lokal maşınımızdan parolsuz daxil olmağa imkan verir.
> su - postgres
> psqlİndi isə SQL kodumuzu yazaq və konsoldan çıxaq:
CREATE USER os_user;
CREATE DATABASE my_database;
REVOKE ALL ON DATABASE my_database FROM public;
ALTER DATABASE my_database OWNER TO os_user;
\qBaza və istifadəçi hazırdırlar. Proyektin qovluğunu (folder) yaradıb Sqitch ilə işə başlaya bilərik:
> su - os_user
> mkdir my-db-plan
> cd my-db-plan
> git init .
> touch README.md
> git add .
> git commit -am 'Initialize project, add README'Sqitch konfiqurasiya faylları ilə işləyir və onların üç səviyyəsi var: qovluq, OS istifadəçisi və sistem. Gəlin OS istifadəçisi səviyyəsində Sqitch-ə adımızı və elektron poçt ünvanımızı bildirək:
> sqitch config --user user.name 'Firstname Lastname'
> sqitch config --user user.email 'example@gmail.com'İndi Sqitch ilə başlamaq üçün hər şey hazırdır:
> sqitch init my-db-plan --engine pg
Created sqitch.conf
Created sqitch.plan
Created deploy/
Created revert/
Created verify/Sqitch dərhal proyektin strukturunu qurur. Bizi hal hazıda maraqlandıran sqitch.conf faylıdır. Bu faylda proyektimizin lokal konfiqurasiyası saxlanılır. Onun daxili strukturu hal hazırda buna oxşamalıdır:
> cat sqitch.conf
[core]
engine = pg
# plan_file = sqitch.plan
# top_dir = .
# [engine "pg"]
# target = db:pg:
# registry = sqitch
# client = psqlBu konfiqurasiyanı repozitoriyə göndərmək düzgün deyil, amma konfiqurasiya faylının misalını saxlamaq yaxşı fikirdir, ona görə mən faylın adını dəyişdirəcəm:
> mv sqitch.conf sqitch.example.confGenerasiya olunmuş fayl məni qane etmir, bəzi konfiqurasiyaları defolt olaraq proyektin bütün verisyalarında (dev, test, prod) görmək istəyirəm və onları hər dəfə yenidən yazmaq istəmirəm. Bunun üçün sqitch.example.conf faylında olan mətni aşağıdaki ilə əvəz edəcəm:
[core]
engine = pg
plan_file = sqitch.plan
top_dir = .
[engine "pg"]
target = dev
registry = sqitch
client = psql
[target "dev"]
uri = db:pg://username:userpassword@localhost/database
[deploy]
verify = true
[revert]
verify = true
[rebase]
verify = trueGəlin yeni dəişiklikləri versiya kontrol sistemimizə yükləyək:
> git add .
> git commit -m 'Initialize default project structure'Lokal konfiqurasiya faylı iş prosesi zamanı uzaq repozitoriyə səhvən düşə bilər. Problemi aradan qaldırmaq üçün onu .gitignore faylına əlavə etmək lazımdır:
> echo 'sqitch.conf' >> .gitignore
> git add .
> git commit -m 'Add .gitignore'
> cp sqitch.example.conf sqitch.confİndi Sqitch-in lokal baza ilə işləməsi üçün faylın target bölümünü dəyişdirmək qaldı:
[target "dev"]
uri = db:pg:my_databaseYoxlayaq işləyirmi:
> sqitch status
# On database dev
No changes deployedƏla, işlədi. Gəlin ilk miqrasiyamızı yaradaq:
> sqitch add users -n 'Add users table'Bazamıza users cədvəlini əlavə edəcəyik. Bunun üçün ./deploy qovluğunda olan users.sql faylını aşağıdaki kodla dəyişdirməliyik:
-- Deploy my-db-plan:users to pgBEGIN;CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email TEXT NOT NULL,
password_hash TEXT NOT NULL,
date_created TIMESTAMPTZ NOT NULL DEFAULT now(),
is_verified_email BOOLEAN NOT NULL DEFAULT FALSE
);COMMIT;
İndi biz Sqitch-i işə sala bilərik:
> sqitch deploy
Deploying changes to dev
+ users .. okƏla, Sqitch dəyişiklikləri bazamıza yüklədi. Əmin olmaq üçün bazaya daxıl ola bilərik:
> psql -d my_database
> \dPostgres bizə sxemimizdə olan users cədvəlini göstərəcək. İş bununla bitmir. Biz miqrasiyanın qaldırılma (up) skriptini yaratdıq, amma onun endirilmə (down) skriptini də yazmaq lazımdır. ./revert/users.sql faylına aşağıdaki kodu yazmaq lazımdır:
-- Revert my-db-plan:users from pgBEGIN;DROP TABLE users;COMMIT;
Gəlin bunu da yoxlayaq:
> sqitch revert -y
Reverting all changes from dev
- users .. okrevert komandasını bu formada istifadə etməyi tövsiyə görmürəm, çünki bu halda o bütün qaldırılmış miqrasiyaları endirir, yəni bazada olan bütün məlumatlar məhv olunur. Onun əvəzinə to parametirindən istifadə olunmalıdır, y bayrağı isə istifadə olunmamalıdır. y bayrağı istifadə olunmadıqda, revert işə düşməzdən əvvəl sizdən əmin olub olmadığınızı soruşacaq. Bu sizə səhvən revert-i çağırdığınız zamanı kömək edə bilər. Məsələn:
> sqitch revert --to @HEAD^
Revert changes to *some_migration* from dev? [Yes]Əvvəl miqrasiyamızı yenidən qaldıraq. Onu necə edəcəyimizi artıq bilirik. Amma Sqitch-in yaratdığı qovluqların arasında biri qaldı — ./verify. Bu qovluqda yoxlama skriptləri saxlanılır. Gəlin ./verify/users.sql faylını da qaydasına salaq. Yoxlanış üçün skript bazada olan məlumata dəymədən cədvələ müraciyət etməlidir, və hər şey yaxşıdırsa çıxmalıdır, əks təqdirdə səhv atmalıdır (error):
-- Verify my-db-plan:users on pgBEGIN;SELECT
id,
email,
password_hash,
date_created,
is_verified_email
FROM customers
WHERE FALSE;ROLLBACK;
İndi konsolda yoxlayaq:
> sqitch verify
Verifying dev
* users .. ok
Verify successfulHər şey işlədi. Əgər bazada cədvəlimiz ya da onun heç olmasa bir sütunu əksik olsaydı biz səhvi ekranımızda görəcəydik. İndi hər şeyi Git-ə yükləmək qaldı:
> git add .
> git commit -m 'Add users table'Gözümüzdən yayınan ancaq sqitch.plan faylı qaldı. Bu faylda yaratdığımız miqrasiyalar qeyd olunur. Əlavə olaraq tarix üçün Sqitch bazada bir cədvəl yaradır və bizim etdiyimiz bütün qaldırma və endirmələrimizi qeyd edir. Bu bazanın konsistentliyini saxlamaq üçün lazımdır.
İndi biz proyektimizə uzaq repozitori (remote) əlavə edib onu oraya yükləyə bilərik. Ordan onu istənilən platformaya yükləyib sqitch deploy komandası vasitəsi ilə, bazamızın kopyasını asanlıqla yarada bilərik (təbii ki, bazaların ancaq sxemi eyni olacaq, məlumatların sinxronizasiyası dəyişiklik menecmentinə aid deyil).
Əlbətdə ki, bu məqalə Sqitch ilə işləməyi tam formada öyrətmir. Burada ancaq ən vacib anları qeyd etdim. Amma təsəvvürün yaradılması üçün bu məlumat yetəri qədərdir. Əgər siz layihənizin xüsusiyyətlərinə əsasən məlumat bazasının dəyşklik menecmenti üçün freymvorklardan ayrı bir alət istifadə etməyin qərarına gəlsəz, Sqitch-i nəzərə alın. Əminəm ki, onu çox sevəcəksiniz.
Faydalı resurslar:
