הגדרת Liquibase למיגרציות אוטומטיות של בסיסי נתונים ו-CI/CD

מיגרציות ידניות של בסיסי נתונים הופכות שחרור גרסה להגרלה: אי-התאמות בסכימה מתגלות רק בפרודקשן. אנו מגדירים את Liquibase מקצה לקצה — פורסים מיגרציות אוטומטיות בצינור הבנייה והאספקה שלכם ומעבירים לצוות נוהל מוכן. שחרור גרסאות מואץ, ושינויים בסכימה מפסיקים להיות תלויים באדם אחד.

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

הגדרת Liquibase: היכן מיגרציות ידניות שוברות את השחרור

הגדרת Liquibase מתחילה בעובדה פשוטה: כל עוד סכימת בסיס הנתונים מורצת ביד — בסקריפט דרך ssh, בקובץ מתוך משימה, בפקודה בקונסול — פער הסכימה בין סביבת הפיתוח, סביבת הבדיקות והפרודקשן מופיע בלי לשים לב.

תיקונים שבוצעו "במהירות" ישירות על הסביבה אינם נכנסים למאגר, והפריסה הבאה דורסת אותם על גבי גרסה אחרת. מיגרציות בסיס נתונים ידניות נראות נשלטות כל עוד יש שתי סביבות ושלושה אנשים.

המחיר מתגלה בשחרור: כשל בפריסה בגלל שעמודה כבר נוצרה או שהטיפוס לא תאם, והאפליקציה מצפה לסכימה אחרת. משם — החזרת השחרור ידנית, השוואת דאמפים, חיפוש שינוי שנשכח בלוגים ובהתכתבות. חלון הפריסה מתארך, והביטחון שהמיגרציה הבאה תעבור באותה צורה לא מגיע.

Liquibase מתרגם את הסכימה לארטיפקט עם ניהול גרסאות: changelog נמצא לצד הקוד, כל מיגרציה מקבלת מזהה וסכום ביקורת, וסדר ההחלה ועובדת ההרצה נרשמים בטבלת שירות.

הרצה חוזרת לא מחילה שינוי פעמיים, תיקון בדיעבד נתפס לפי סכום הביקורת, והסביבות מתכנסות לסכימה אחת ממקור אחד — בלי קשר לשאלה אם זו פיתוח או פרודקשן.

להלן נפרט איך זה נסגר: מבנה changelog, קונטקסטים ותגיות לסביבות שונות, החזרת שינויים ושילוב מיגרציות בצינור הפריסה.

מה נותנת אוטומציה של מיגרציות: אפקט לפי שלבי האספקה

את האפקט של אוטומציה של מיגרציות מעריכים לא לפי רושם כללי, אלא לפי נקודות מדידות בכל שלב של האספקה. אנחנו מנהלים ארבעה סימנים ומשווים אותם לפני ואחרי ההטמעה — כך רואים מה בדיוק נותן המעבר של שינויי סכימה מפעולות ידניות אל Liquibase.

שחזוריות הסביבות

ניהול גרסאות של הסכימה הופך את מערך המיגרציות למקור האמת היחיד: סביבת הפיתוח, סביבת הבדיקות והסביבה היצרנית נבנות מתיקייה אחת, ולא מתיקונים שנעשו ביד בכל אחת מהן. הבדיקה פשוטה — לפרוס סביבה מאפס ולהשוות את המבנה לסביבה שבה השינויים הורצו בהדרגה: לא אמורים להיות פערים.

זמן הפריסה של שינויים

מיגרציות עוברות במעבר אחד יחד עם שחרור האפליקציה, בלי חלון נפרד לסקריפטים ידניים ובלי תלות בשאלה אם התורן זוכר את הרצף הנדרש. זמן הפריסה מפסיק לגדול עם מספר התיקונים — הוא נקבע לפי היקף השינויים, לא לפי מספר הצעדים סביבם.

השבתה בעת עדכון

הצעדים נבנים לפי הסכמה "הרחבה — מילוי — צמצום": תחילה אובייקטים תואמים, אחר כך העברת נתונים, ולבסוף מחיקת הישן. האפליקציה עובדת על שתי גרסאות של הסכימה בו-זמנית, ולכן השבתה בעת עדכון נעלמת או מצטמצמת עד כדי כך שהמשתמש לא מבחין בה.

שיעור שגיאות הסכימה וסוג התקלות שנעלם

המצב נרשם ביומן המיגרציות שהוחלו, הרצה חוזרת בטוחה, ופער בין סביבות נראה לפני השחרור. עם זה נעלם סוג שלם של תקלות: סקריפט שנשכח בסביבה אחת, התנגשות בין תיקונים של שני מפתחים, החזרת שחרור בלי תוכנית למבנה.

השוואת מצבי מיגרציה: סכימה, נתונים, החזרה

מצב החלת השינויים נבחר לפי אופי המשימה, לא לפי הרגל: להוסיף עמודה או אינדקס — סיפור אחד, להעביר ולנרמל ערכים — סיפור אחר לגמרי. ההבדל נראה בהחזרה: שינוי סכימה ברוב בסיסי הנתונים לא מתבטל אוטומטית, ופעולות על נתונים נעלמות יחד עם הטרנזקציה.

גורם שני — מי יוזם את ההרצה. כל עוד מהנדס מחיל את השינויים ידנית, הסדר מוחזק בהסכמות; בצינור, כלי כמו Liquibase מתעד אותו, ואז קריטי מה בדיוק נמצא במערכי השינויים ואיך נבדקת שלמותם.

מצב מתי מתאים מגבלות
סכימה בלבד נתונים יציבים: טבלאות חדשות, אינדקסים, עמודות בלי העברת ערכים לא מכסה מיגרציות נתונים — העברה ונרמול מכינים בנפרד
סכימה יחד עם נתונים עמודות חדשות עם מילוי, העברות חד-פעמיות, שינויי שמות פעולות ארוכות מחזיקות נעילות, החזרת נתונים עובדת רק בתוך טרנזקציה
מערכי שינויים מוכנים שחרורים חוזרים, כמה סביבות, שחזוריות דרושים סקירה ובקרת שלמות, אחרת הפער יוחל בעיניים עצומות
הרצה ידנית תיקוני חירום ופתרון תקלה אין היסטוריה וחזרתיות, ההחזרה כולה נופלת על המהנדס

את המצב מקבעים לפני השחרור: ממנו תלוי מה ייכנס למערכי השינויים ואיזו החזרה נוכל להציע בעת תקלה.

הגדרת Liquibase בצינור הבנייה והאספקה

הגדרת Liquibase בצינור האספקה יוצאת ממצב הסכימה בפועל, לא מהתיעוד: פערים בין סביבות בדרך כלל צפים בפריסה. להלן סדר העבודות שאנחנו עוברים יחד עם צוות הלקוח.

  1. מיפוי מלאי. משווים סכימות של סביבת פיתוח, קדם-שחרור וייצור, אוספים אובייקטים שחיים מחוץ למערכת המיגרציות ופערים שהצטברו מתיקונים ידניים.
  2. מבנה changelog. מחלקים את השינויים לקבצים לפי שחרורים, קובעים פורמט אחיד למזהים ומחברים קובץ אב ראשי — היסטוריית התיקונים נקראת בלי ארכיאולוגיה.
  3. תיאור השינויים. כל שינוי מוגדר יחד עם פעולה הפוכה: החלה והחזרה נמצאות באותו מערך, ולכן החזרת שחרור לא הופכת לעבודה ידנית תחת עומס.
  4. פרמטרים להרצה. מגדירים קונטקסטים ותגיות לפי סביבות: שינויי שירות לא עוברים לסביבת הייצור, ופעולות כבדות רצות בזרם נפרד.
  5. בדיקת מיגרציות. מריצים את השינויים בסביבת קדם-שחרור על עותק של נתוני הייצור — בודקים זמן ריצה, נעילות, תוכנית שאילתות ועלות החזרה.
  6. יומן גרסאות שהוחלו. טבלת הבקרה הופכת למקור האמת היחיד על מצב בסיס הנתונים: ממנה רואים מה ומתי הוחל, וממנה מתבצעת התאוששות אחרי כשל.
  7. מסירת נוהל. מעבירים לצוות כללים להוספת שינויים, בדיקה אוטומטית בצינור וסדר פעולה בהתנגשות — מיגרציות מפסיקות להיות תחום של מהנדס אחד.

מה נשאר במאגר: קבצים, סכימות, נהלים

התוצר של הפרויקט הוא לא אוסף תיקונים חד-פעמיים בבסיס הנתונים, אלא סביבת מיגרציות ניתנת לשחזור: סביבה נקייה עולה בפקודה אחת, ולא נשארים פערים בין הסביבות. אנחנו מוסרים לא רק קוד, אלא גם ארטיפקטים שלפיהם צוות הלקוח ממשיך לעבוד בלעדינו.

  • קבצי שינויים — תיאורים מסודרים של מיגרציות עם פעולות הפוכות וחלוקה למערכים לוגיים; רואים איזה שינוי שייך לאיזו משימה ואיך להסיר אותו.
  • סכימת סביבות — אילו סביבות קיימות, במה הן נבדלות בהרשאות ובנתונים, היכן ההחלה אוטומטית בזמן בנייה והיכן רק ידנית עם אישור.
  • נוהל פריסה — רצף הצעדים, חלון ההחלה, האחראי על ההרצה, סדר הפעולות בשינוי לא תואם וכללי עצירה.
  • מדיניות גישה לבסיס הנתונים — חשבון נפרד למיגרציות עם ההרשאות המינימליות הנדרשות, תפקידים לקריאה ולכתיבה, איסור על תיקונים ידניים של המבנה בעקיפת המאגר.
  • סדר ההחלה בסביבות שונות — מסביבת בדיקות ועד סביבת עבודה, עם בדיקה על עותק נתונים וסנכרון מספרי שינויים.
  • הוראות למשמרת תורנית — מה לבדוק ביומן, איך לאבחן מיגרציה תקועה, איך לחזור אחורה ומי להפעיל.
  • מסירת תיעוד — תיאור מודל הנתונים, מפת שינויים, אחראים וסדר הסלמה; הקבלה נעשית לפי צ'ק-ליסט, לא לפי זיכרון.

מקרה בוחן: מיגרציות תחת בקרה אוטומטית

הלקוח פיתח שירות עם שלוש סביבות: פיתוח, סביבת קדם-פרודקשן וסביבת עבודה. תיקוני הסכימה הורצו ידנית — מהנדס התחבר לבסיס הנתונים, הריץ קובץ עם שינויים וחזר על אותו דבר בסביבה הבאה.

פערים בין הסביבות חיפשו בעיניים, לפני השחרור השוו את מבנה הטבלאות, ואת סדר החלת הקבצים החזיקו בראש ובהתכתבות.

את השינויים העבירו אל Liquibase: כל צעד מתואר במערך נפרד במאגר, לצד הקוד, ומוחל אוטומטית בזמן פריסה. מצב הסכימה נקבע כעת לפי רשימת המערכים שהוחלו, ולא לפי הזיכרון של מהנדס מסוים, — לכל סביבה מגיע בדיוק מה שכבר עבר פיתוח.

מדדים לפני ואחרי

הכנת מבנה בסיס הנתונים לפני שחרור: היה 40–60 דקות של עבודה ידנית תלויה באדם אחד, הפך ל-6–8 דקות של ריצה אוטומטית. פניות הקשורות לסכימה ברבעון: שבע לפני המעבר ואחת אחרי — וגם היא נתפסה בסביבת קדם-פרודקשן, לא בסביבת העבודה.

נעלם סוג שלם של תקלות: החלה חוזרת של אותו שינוי, סדר קבצים שגוי וסביבה שנשכחה. היסטוריית ההחלות נשמרת בבסיס הנתונים עצמו, ולכן אפשר לחזור למצב הסכימה הקודם באופן ממוקד, ולא בשחזור מגיבוי לילי של כל הסביבה.

מה לעשות אם בסיס הנתונים כבר פרוס ויש פערים?

בסיס נתונים פרוס מוכנס למצב מנוהל לא מהמיגרציה הראשונה, אלא מנקודת ייחוס מקובעת.

הצעד הראשון — מיפוי מלאי של שינויים: מוציאים את הסכימה בפועל (DDL-דאמפ או קטלוג מערכת), משווים אותה למה ש-changelog מתאר, ומחלקים את הפערים לשלוש קבוצות — שהוחלו ידנית, חסרים, שנבדלו בטיפוס או באורך השדות. כל עוד התמונה הזו לא נאספה, כל מיגרציה היא הגרלה עם הנתונים.

הלאה — baseline: Liquibase בפקודה changelog-sync מסמן changeSet קיימים כבוצעו, בלי להריץ אותם, ותג על מצב הסכימה הנוכחי הופך לנקודת החזרה. אחרי זה בסיס הנתונים מובא למצב היעד לפי גרסת changelog, וכל השינויים הבאים עוברים רק דרך מיגרציות — ביד לפרודקשן כבר לא נכנסים.

מעבר בטוח נבנה על תצוגה מקדימה: קודם ריצה על עותק עם נפח נתונים אמיתי, אחר כך update-sql — לראות מה בדיוק ייכנס לבסיס הנתונים, ורק אחר כך החלה.

כל changeSet רץ בטרנזקציה משלו היכן שמערכת ניהול בסיס הנתונים תומכת בכך, נעילה על יומן המיגרציות לא נותנת לשני שחרורים להתחיל במקביל, ושינויים עם נעילות כבדות מוצאים לחלון מתואם.

אם הסכימה תוקנה מחוץ למיגרציות, זה ייתפס לפי סכום הביקורת של הרשומות: validate ו-status עוצרים את הבנייה לפני הפריסה, לא אחריה. כך פערים חד-פעמיים הופכים ל-baseline מקובע, ולא לסנכרון ידני קבוע של שתי גרסאות סכימה.

ספקות טכניים לפני הטמעת מיגרציות

חלק מהספקות נסגר במכניקה של המיגרציות עצמן — יומן changeSet שהוחלו והשוואה לפי סכומי ביקורת. את השאר מספקים הנוהל ואופן הארגון של changelog. אנחנו עונים על שאלות שעולות לרוב בשלב ההערכה.

מפתחים מתקנים את בסיס הנתונים מחוץ למיגרציות — זה ישבור את התהליך?

שינוי שלא הוכנס ל-changelog לא נראה ליומן: בהרצה הבאה השוואת סכום הביקורת ת�ראה פער, והמיגרציה תיעצר. לכן גישה ישירה לסביבות נסגרת, ותיקוני חירום מוגדרים כ-changeSet נפרד — הוא נכנס להיסטוריה ומשוחזר בסביבות האחרות.

כמה צוותים מבצעים מיגרציה של הסכימה בו-זמנית — תהיה התנגשות?

כל מודול מנהל changelog משלו ומתחבר למשותף דרך קובץ אב, ולכן הצוותים לא מצטלבים ב-changeSet של אחרים. נעילת שירות על היומן מסירה את המרוץ אם המיגרציות מופעלות במקביל.

איך לחזור ממיגרציה שנכשלה?

עבור changeSet עם rollback תואם, ההחזרה מתבצעת בפקודה אחת. עבור פעולות בלתי הפיכות — מחיקה או שינוי שם של עמודה — מכינים מראש מיגרציה מפצה ובודקים אותה על עותק של בסיס הנתונים בעבודה.

מי ואיך מריץ שינויים בסביבת העבודה?

מיגרציות מוחלות על ידי הצינור אחרי סקירת changeSet, לא בידי אדם. גישה ישירה לבסיס הנתונים בעבודה נשארת אצל המהנדס התורן ומתועדת בלוגים — נוהל הגישה מתואר בתיעוד.

הסכימות בסביבות נבדלו — מה לעשות?

המקור היחיד — changelog, והבדלים בין סביבות מתוארים בקונטקסטים ובתגיות: בסביבה מוחלת תת-קבוצה של מיגרציות, והסכימה מובאת לגרסה הנדרשת בלי סקריפטים ידניים.

נדון במשימה: מה צריך כדי להתחיל מיגרציות

תחילת העבודה לא דורשת מהלקוח דבר מלבד גישות למה שהוא כבר משתמש בו. אנחנו לא מבקשים לפתוח חשבונות חדשים או לכתוב מחדש את הסכימה — בשלב הראשון מספיק להבין איך שינויים נכנסים לבסיס הנתונים היום, ולהשוות את זה לתהליך היעד.

מה נדרש מכם בכניסה:

  • רשימת בסיסי נתונים וסביבות: פיתוח, בדיקות, קדם-פרודקשן, פרודקשן — והיכן מיגרציות מוחלות היום ידנית.
  • מאגר עם סקריפטי SQL נוכחיים או תיאור הסכימה — לפיו אוספים baseline ורואים פערים בין הסביבות.
  • גישות למערכת הבנייה ולשרת המיגרציות: משתמש שירות עם הרשאות לשינוי סכימה, אבל בלי הרשאות לנתוני פרודקשן.
  • נהלים: חלונות תחזוקה, דרישות להחזרה, מי מאשר החלה בפרודקשן.
  • אחראי על הסכימה מצד המוצר — זה שמאשר תיקונים לפני פריסה.

הלאה הסדר הוא כזה: דנים במשימה ובתהליך הנוכחי, מעריכים היקף — מספר בסיסי הנתונים, גודל ה-baseline, מורכבות תיקונים מתנגשים. לפי תוצאות ההערכה מכינים תוכנית להעברת השינויים אל Liquibase: מאיזו סביבה מתחילים, איך מסנכרנים סקריפטים שכבר הוחלו, איך נראית החזרה בכל שלב.

את התוכנית מתאמים יחד עם לוחות זמנים ונקודת האל-חזור — הרגע שאחריו תיקוני סכימה עוברים רק דרך מיגרציות.