לדלג לתוכן

מה זה טרנזקציה במסד נתונים - ולמה בלעדיה אפליקציית בנק תישבר

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

הבעיה שהמצאת הטרנזקציה פותרת

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

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

אז מה זו בעצם טרנזקציה

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

בקוד, זה נראה בערך כך:

BEGIN;

UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

COMMIT;

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

עקרונות ה-ACID, בלי הבלבול המקובל

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

  • אטומיות - Atomicity. זה בדיוק מה שהסברנו - הכל או כלום, אין מצב חלקי.
  • עקביות - Consistency. מסד הנתונים תמיד עובר ממצב תקין למצב תקין. אם יש חוק שאומר "היתרה לא יכולה להיות שלילית", טרנזקציה שתפר את החוק הזה תיכשל ותתבטל.
  • בידוד - Isolation. טרנזקציות שרצות במקביל לא "רואות" זו את התוצאות החלקיות של זו. אם שני אנשים מבצעים פעולות על אותו חשבון בו-זמנית, כל אחד רואה תמונה עקבית, לא מצב באמצע שינוי.
  • עמידות - Durability. ברגע שטרנזקציה הצליחה (COMMIT), השינוי נשמר לצמיתות, גם אם השרת קורס בשנייה שאחרי. הנתונים כבר נכתבו בצורה בטוחה לדיסק.

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

מתי אתם באמת צריכים לחשוב על טרנזקציות

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

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

למה זה נושא שלא כדאי לדלג עליו

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

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

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

הצטרפו לקהילה בדיסקורד