Heç vaxt olmamışdı, amma yenə də oldu!
Bir layihə çərçivəsində Liquibase istifadə etməyə qərar verdik ki, gələcəkdə problemlərdən qaçaq. Aydındır ki, komandanın gənc üzvlərinin hamısı bunu düzgün şəkildə istifadə edə bilmir. Daxili bir workshop keçirdim və onu bir məqaləyə çevirmək qərarına gəldim.
Məqalə, Liquibase da daxil olmaqla, relasiyalı verilənlər bazası köçürmə alətləri ilə işləyərkən qarşılaşa biləcəyiniz üç əsas tuzağı və faydalı məsləhətləri əhatə edir. Junior və Middle səviyyəli Java proqramçıları üçün nəzərdə tutulub, daha təcrübəli proqramçılar üçün isə, çox güman ki, artıq tanış olanları strukturlaşdırmaq və təkrarlamaq məqsədilə maraqlı ola bilər.

Liquibase və Flyway — Java dünyasında relasiyalı strukturların versiyalarını idarə etmək üçün əsas rəqib texnologiyalardır. Birincisi tamamilə pulsuzdur və praktikada daha çox istifadə olunur, beləliklə bu məqalənin qəhrəmanı olaraq Liquibase seçilmişdir. Bununla belə, təsvir olunan bəzi praktikalar sizin tətbiqinizin memarlığından asılı olaraq universal ola bilər.
Relasiyalı strukturların köçürülməsi, relasiyalı verilənlər bazalarının zəif çevikliyi ilə mübarizənin qaçılmaz bir yolu olmuşdur. OOP stilinin məşhur olduğu dövrdə, verilənlər bazası ilə işimiz bir dəfə sxemi təsvir etmək və bundan sonra onu daha bir dəfə dəyişdirməmək nəzərdə tutulurdu. Lakin reallıq belədir ki, hər şey dəyişir və cədvəllərdə dəyişikliklər tez-tez tələb olunur. Təbii ki, bu proses özlüyündə ağrılı və xoşagəlməz ola bilər.
Texnologiyanı və kitabxananı layihənizə əlavə etməklə bağlı instruksiyaları derinliyinə getməyəcəyəm, bu mövzuda kifayət qədər məqalə yazılıb:
Bundan əlavə, artıq faydalı məsləhətlər mövzusunda mükəmməl bir məqalə də var:
Məsləhətlər
Köçürmə ilə bağlı problemləri həll edərkən meydana çıxan öz məsləhət və şərhlərimi paylaşmaq istəyirəm.
1. İşə başlamazdan əvvəl Liquibase
Kitabxananın istifadəsini çətinləşdirə biləcək sadə, amma çox vacib məsələlərdən bəhs edilir. Məsələn, çəncsetlərin idarə edilməsində strukturlaşdırılmamış yanaşma istər-istəməz qarışıqlıq və sındırılmış miqrasiya ilə nəticələnəcək. Əgər bir-birinə bağlı verilənlər bazası strukturu və xidmətlərin loqikasına dəyişikliklər bərabər zamanda tətbiq edilmirsə, qırmızı testlər və ya sındırılmış mühitlər ilə rastlaşma ehtimalı yüksəkdir. Həmçinin, Liquibase-in rəsmi saytında miqrasiya əsas skriptləri ilə birlikdə rollback skriptlərinin hazırlanması və yoxlanılması haqqında tövsiyələr var. Həmçinin, məqalədə miqrasiya və rollback mexanizmlərinə aid kod nümunələri var.
2. Miqrasiya vasitələrinin istifadəsinə başlayanda - verilənlər bazası strukturunda manual düzəlişlər etməyə icazə verməyin.
Deyildiyi kimi: "Bir dəfə Persil - həmişə Persil". Əgər tətbiqinizin verilənlər bazası Liquibase vasitələri ilə idarə olunmağa başladısa - hər hansı manual dəyişikliklər dərhal qeyri-konsistent vəziyyətə səbəb olur və çəncsetlərə etibar tamamilə itirilir. Potensial risklər - bərpa üçün bir neçə saat itirilmiş zaman, daha pis halda - serverin sındırılmasıdır. Əgər komandanızda "köhnə təhsilli" bir DBA Architect varsa, ona sadə bir SQL Developer kimi verilənlər bazasını öz iradəsinə görə düzəldəcəyi halda hər şeyin necə pis olacağını diqqətlə izah edin.
3. Əgər çəncset artıq repozitoriyaya göndərilmişsə, redaktə etməlisiniz.
Əgər başqa bir tərtibatçı pull edir və sonradan redaktə ediləcək çəncseti tətbiq edirsə - tətbiq işə salındıqda xəta alanda sizi gözəl sözlə xatırlayacaq. Əgər çəncsetin redaktəsi bir şəkildə inkişaf mühitinə sızarsa - hotfix-lərin sürüşkən yolunu izləmək lazım olacaq. Problemin kökü dəyişikliklərin hash cəmi ilə doğrulanmasında dayanır - Liquibase-in əsas mexanizmi. Çəncset kodunun redaktəsi hash cəmini dəyişir. Çəncsetlərin redaktəsi yalnız bütün verilənlər bazasını sıfırdan itkisiz olaraq inkişaf etdirmək imkanı olduğu zaman mümkündür. Belə bir halda SQL və ya XML kodunun refaktoru əslində həyatı asanlaşdıraraq miqrasiyaları daha oxunaqlı edə bilər. Məsələn, tətbiqin başlanğıcında ilkin verilənlər bazası sxeması komanda daxilində razılaşdırılıb.
4. Mümkünsə, yoxlanılmış verilənlər bazası ehtiyat nüsxələri saxlayın.
Burada, düşünürəm ki, hər şey aydındır. Əgər təsadüfən miqrasiya uğursuz keçərsə, hər şeyi geri qaytarmaq mümkündür. Liquibase-də dəyişikliklərin geri qaytarılması üçün bir alət var, amma geri qaytarma skriptlərini də eyni tərtibatçı yazır və onlarda əsas çəncset skriptlərindəki kimi problemlər ola bilər. Bu, hər halda ehtiyat nüsxələri ilə təhlükəsizliyə diqqət yetirməyin faydalı olduğunu göstərir.
5. Mümkün olduqda, inkişafda yoxlanılmış verilənlər bazası ehtiyat nüsxələrindən istifadə edin.
Əgər bu müqavilələrə və məxfilik qaydalarına zidd deyilsə, bazada şəxsi verilənlər yoxdursa və o, iki günəş qədər ağır deyilsə — canlı serverlərdə tətbiq etmədən əvvəl onu inkişaf etdiricinin maşınında işə salıb, migrasiya zamanı potensial problemlərin 100%-ə qədərini hesablaya bilərsiniz.
6. Komandadakı digər inkişafçılarla ünsiyyət qurun
Düzgün təşkil edilmiş inkişaf prosesində komandadakı hər kəs kimlə məşğuldur bilir. Reallıqda bu, tez-tez belə olmur, buna görə də, öz vəzifəniz çərçivəsində verilənlər bazasının strukturunda dəyişiklik edirsinizsə, bütün komandaya əlavə məlumat vermək yaxşıdır. Əgər kimsə eyni anda dəyişiklik edirsə — diqqətlə təşkilatlanmalısınız. İşinizi bitirdikdən sonra həmkarlarla ünsiyyətdə olmaq da faydalıdır, yalnız başlayanda deyil. Çoxsaylı potensial problemlər dəyişikliklər dəstəyi mərhələsində həll oluna bilər.
7. Nə etdiyinizi düşünün!
Görünüşcə, hər hansı vəziyyət üçün keçərli olan öz-özünə aydın bir tövsiyədir. Lakin bir çox problemin qarşısını almaq mümkün olardı, əgər inkişafçı bir daha etdiklərini və bunun nələrə təsir göstərə biləcəyini analiz etsəydi. Migrasiyalarla işləmək həmişə əlavə diqqət və ehtiyat tələb edir.
Tələlər
İndi yuxarıdakı tövsiyələrə əməl etmədikdə qarşılaşa biləcəyiniz tipik tələləri və əslində nə etməli olduğunuzu nəzərdən keçirək.
Vəziyyət 1. İki inkişafçı eyni anda yeni dəyişiklik dəstləri əlavə etməyə çalışır

Vasya və Petya bir-birlərindən xəbərsiz 4-cü versiya üçün dəyişiklik dəsti yaratmaq istəyirlər. Onlar verilənlər bazasının strukturunda dəyişikliklər ediblər və fərqli dəyişiklik dəstəyi olan pull request göndərmişlər. Sonra bir növ hərəkət mexanizmi təqdim edilir:
Necə həll etmək olar
- Hər hansı bir yolla həmkarlar bir-birlərinin dəyişiklik dəstlərinin hansı sırada gedəcəyini razılaşmalıdır, məsələn, Petya'nın ilk tətbiq edilməlidir.
- Bir nəfər ikinci dəstə özünə birləşdirməli və Vasya'nın dəyişiklik dəstini 5-ci versiya ilə işarələməlidir. Bu, Cherry Pick və ya diqqətli birləşdirmə ilə edilə bilər.
- Dəyişikliklərdən sonra həyata keçirilən əməliyyatların doğruluğunu mütləq yoxlamaq lazımdır.
Əslində, Liquibase mexanizmləri depoda iki 4-cü versiya dəyişiklik dəstinin olmasına imkan tanıyır, buna görə də hər şeyi olduğu kimi saxlaya bilərsiniz. Yəni, sadəcə fərqli adlarla iki 4-cü versiya dəyişiklik olacaq. Belə bir yanaşma ilə daha sonra verilənlər bazası versiyalarında çox çətinləşir.
Bundan əlavə, Liquibase hobbitlərin evinin içində bir çox sirr saxlayır. Onlardan biri validCheckSum açarıdır ki, bu da 1.7 versiyası ilə meydana gəldi və verilənlər bazasında saxlanılanlardan asılı olmayaraq müəyyən bir dəyişiklik dəsti üçün düzgün hash dəyərini göstərməyə imkan tanıyır. Sənədləşmə aşağıdakıları deyir:
Bu dəyişikliyin etibarlı sayılan checksum'unu əlavə edin. Bu, verilənlər bazasında artıq işlədilmiş dəyişikliklər üçün səhv meydana gəlmədən dəyişikliklərinizi etməyə ehtiyac duyduğunuz zaman əsasən istifadə olunur (tövsiyə edilən bir prosedur deyil)
Bəli, bəli, belə bir prosedur tövsiyə edilmir. Amma bəzən güclü aydın sehrbaz həm də qaranlıq texnikalardan istifadə edir.
Hesab 2. Məlumatlardan asılı olan köçürmə

Təsəvvür edin ki, canlı serverlərdən verilənlər bazalarının ehtiyat nüsxələrini istifadə etmək imkanınız yoxdur. Petya bir dəyişiklik dəstəsi yaradıb, onu yerli olaraq yoxlayıb və öz fikrinin doğruluğuna tam əmin olaraq inkişaf mühitinə (dev) pull request göndərib. Layihənin lideri ehtiyat üçün Petya'nın bunu yoxlayıb-yoxlamadığını soruşub və sonra onu birləşdirib. Amma dev serverdə yerləşdirmə başa çatmayıb.
Əslində belə bir şey mümkündür və buna heç kim sığortalanmır. Bu, cədvəl strukturlarının dəyişdirilmələrinin hansısa şəkildə verilənlər bazasında spesifik məlumatlara bağlı olduğu halda baş verir. Aydındır ki, əgər Petya'nın bazası yalnız test məlumatları ilə doludursa, o, bütün problemli hallarını əhatə etməyə bilər. Məsələn, cədvəl silinərkən aşkar edilir ki, silinən cədvəldən bağlı olan digər cədvəllərdə Foreign Key ilə qeydlər mövcuddur. Yaxud da, sütunun tipinin dəyişdirilməsi zamanı aşkar edilir ki, məlumatların 100%-i yeni tipə çevriləyə bilmir.
Necə həll etmək olar
- Veriləri uyğun formada gətirmək üçün köçürmə ilə birlikdə bir dəfə tətbiq olunacaq xüsusi skriptlər yazmaq lazımdır. Bu, məlumatların köçürülməsi problemini yeni strukturlara keçirdikdən sonra həll etmənin ümumi yoludur, amma buna bənzər bir şey ikincil vəziyyətlərdə də tətbiq oluna bilər. Belə bir yol əlbəttə ki, hər zaman əlçatan deyil, çünki canlı serverlərdə məlumatları redaktə etmək təhlükəli və hətta ziyanlı ola bilər.
- Başqa bir çətin yol — mövcud dəyişiklik dəstəsini redaktə etməkdir. Çətinlik ondan ibarətdir ki, bu dəstənin artıq mövcud olduğuna görə istifadə olunduğu bütün verilənlər bazaları bərpa olunmalıdır. Tamamilə mümkündür ki, bütün backend komandası əsrə bərabər verilənlər bazasını sıfırdan yerli olaraq yerləşdirməyə məcbur olsun.
- Və ən universal yol — məlumat problemi inkişaf etdirici mühitinə köçürməkdir ki, eyni vəziyyəti yoxlayaraq və problemi yan keçməyə imkan verən yeni bir dəyişiklik dəstəsi əlavə edəsiniz.

Ümumiyyətlə, məlumatların tərkibcə istehsal serverinin məlumat bazasına daha çox bənzəyirsə, köçürmə problemlərinin baş vermə ehtimalı daha azdır. Və əlbəttə ki, dəyişiklik dəstəsini repositora göndərməzdən əvvəl, onun nəyisə sındırıb-sındırmayacağına bir neçə dəfə düşünmək lazımdır.
Hesab 3. Liquibase artıq istehsala çıxarkən tətbiq olunmağa başlayır
Təsəvvür edin ki, team lead Petya'dan layihəyə Liquibase'i qoşmağı istəyib, lakin layihə artıq istehsaldadır və artıq mövcud verilənlər bazası strukturu var.
Beləliklə, problem ondadır ki, yeni serverlər və ya inkişaf etdirici maşınlarında bu cədvəllərin məlumatları sıfırdan yaradılmalıdır, mövcud mühit isə yeni dəyişiklik dəstlərini qəbul etməsilə bağlı ardıcıllıqda saxlanılmalıdır.
Necə həll etmək olar
Burada bir neçə yol var:
- Birincisi və ən açıq olanı — yeni mühitin başlanğıcında əl ilə tətbiq edilməli bir ayrı skriptin olmasıdır.
- İkincisi — daha az açıq olanı, ayrı bir Liquibase Kontekstində olan bir Liquibase miqrasiya olmasıdır və onun tətbiq edilməsidir. Liquibase Konteksti haqqında daha çox məlumatı burada oxuya bilərsiniz: . Ümumilikdə bu, məsələn, test etmə üçün uğurla tətbiq edilə bilən maraqlı bir mexanizmdir.
- Üçüncü yol bir neçə mərhələdən ibarətdir. İlk olaraq mövcud cədvəllərin miqrasiya yaradılması lazımdır. Sonra bu, bir mühitdə tətbiq olunmalı və bununla onun hash dəyəri əldə edilməlidir. Növbəti addım isə bizim boş serverimizdə boş Liquibase cədvəllərinin başlatılmasıdır və dəyişiklik dəstlərinin tarixçəsində "sanki tətbiq edilmiş" dəyişiklik dəsti haqqında qeydi manuel olaraq yazmalıyıq. Beləliklə, artıq mövcud serverdə tarixçe 2-dən başlayacaq, bütün yeni mühitlər isə eynilə davranacaq.

4-cü vəziyyət. Miqrasiya prosesi çox böyük olur və tamamlanmır.
Xidmətin inkişafı başlayanda adətən Liquibase xarici asılılıq kimi istifadə olunur və bütün miqrasiyalar tətbiqin başlayışı zamanı icra olunur. Lakin zaman keçdikcə aşağıdakı hallara rast gələ bilərsiniz:
- Miqrasiyalar çox böyük olur və uzun müddət icra edilir.
- Eyni zamanda, paylanmış mühitlərdə, yəni bir neçə verilənlər bazası serverində eyni anda miqrasiya etmək ehtiyacı yaranır.
Bu halda, miqrasiyaların çox uzanması tətbiqin başlanğıcında zaman aşımına səbəb olacaq. Buna əlavə olaraq, tətbiq hər bir instans üçün ayrı-ayrılıqda miqrasiyaların aparılması fərqli serverlərin sinxronlaşdırılmamasına səbəb ola bilər.
Necə həll etmək olar
Belə hallarda layihəniz artıq böyüyüb, mümkün ki, tam yetkin vəziyyətdədir və Liquibase artıq ayrı bir müstəqil alət kimi çıxış etməyə başlayır. Məsələ ondadır ki, Liquibase bir kitabxana olaraq jar faylına yığılır və həm layihənin içində asılılıq olaraq, həm də müstəqil bir şəkildə işləyə bilər.
Müstəqil rejimdə, miqrasiyaların tətbiqini CI/CD mühitinizə və ya sistem administratorlarınızın güclü imkanlarına həvalə edə bilərsiniz. Bunun üçün Liquibase komanda xətti lazımdır . Belə bir rejimdə, bütün lazım olan miqrasiyalar tamamlanandan sonra tətbiqin başladılması imkanı yaranır.
Çıktı
Əslində, DB migrasiyaları ilə iş zamanı daha çox maneələr ola bilər və bunların çoxu yaradıcı yanaşma tələb edir. Alətdən düzgün istifadə edildikdə, bu maneələrin əksəriyyətindən qaçınmaq mümkündür. Mən müxtəlif formalarda bu problemlərlə rastlaşmışam, bəziləri isə mənim səhvlərimin nəticəsi olub. Əsasən bu baş verir, əlbəttə, diqqətsizlikdən, ancaq bəzən də aləti istifadə etməyi bacarmama səbəbindən.
Mənbə: habr.com


