Menu

Savepoints ב-SQLite: טרנזקציות מקוננות עם ROLLBACK TO

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

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

Savepoint הוא סימנייה עם שם בתוך טרנזקציה

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

זה מה ש-savepoint עושה. מציבים סימנייה עם שם, עושים קצת עבודה, ואז או שומרים את העבודה (RELEASE) או חוזרים לסימנייה (ROLLBACK TO).

החיוב של Ada והזיכוי של Boris נשארים שניהם. העדכון השגוי ל-Nobody בוטל בלי לאבד את שאר הטרנזקציה.

שלוש הפקודות

שלוש פקודות הן כל ה-API:

  • SAVEPOINT name: הצבת סימנייה.
  • RELEASE SAVEPOINT name: שמירת העבודה שנעשתה מאז הסימנייה, והסרת הסימנייה.
  • ROLLBACK TO SAVEPOINT name: ביטול כל מה שנעשה מאז הסימנייה. הסימנייה נשארת במקומה כדי שאפשר יהיה לנסות שוב.

המילה SAVEPOINT אחרי RELEASE ואחרי ROLLBACK TO היא אופציונלית: גם RELEASE risky וגם ROLLBACK TO risky עובדות.

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

Savepoints בלי טרנזקציה חיצונית

הנה תפנית קטנה: אפשר להריץ SAVEPOINT בלי BEGIN לפני כן. SQLite פותחת בשקט טרנזקציה בשבילכם, וה-savepoint החיצוני ביותר משחק את התפקיד של הטרנזקציה עצמה. RELEASE על ה-savepoint הזה מבצע commit, ו-ROLLBACK TO חוזר אחורה בלי לבצע commit.

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

קינון savepoints

Savepoints נערמים. אפשר להציב אחד בתוך אחר ולבטל את הפנימי בלי לגעת בחיצוני:

התוכן הסופי: a, b, d. החזרה ל-inner הסירה את c, אבל השאירה שלמה את העבודה שנעשתה לפני inner (ההכנסה של b), והטרנזקציה המשיכה.

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

גם b וגם c נעלמו. ROLLBACK TO outer מחזיר אחורה את כל מה שנעשה מאז ש-outer הוצב, כולל inner וההכנסה של c.

למה להשתמש ב-savepoints?

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

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

זה גם הדפוס שבו ORM וכלי מיגרציה מממשים טרנזקציות מקוננות: הם לא באמת מקננים בלוקים של BEGIN (ב-SQLite אי אפשר), הם ממפים קריאות מקוננות ל-savepoints.

כמה דברים שכדאי לשים לב אליהם

כמה פרטים שתופסים אנשים חדשים ב-savepoints:

  • COMMIT תמיד מבצע commit לכל הטרנזקציה. לא משנה כמה savepoints פתוחים יש לכם: COMMIT (או הכינוי שלו END) סוגר את כל הטרנזקציה החיצונית. אל תחשבו על RELEASE כעל commit חלקי: שום דבר לא עמיד עד שהטרנזקציה העוטפת מבצעת commit.
  • ROLLBACK (בלי TO) מבטל הכול. הוא מסיים את הטרנזקציה וזורק את כל ה-savepoints הפתוחים. השתמשו ב-ROLLBACK TO name כשאתם רוצים להשאיר את הטרנזקציה בחיים.
  • Savepoint נשאר פתוח עד שמשחררים אותו או חוזרים דרכו. אם שוכחים RELEASE לא מאבדים נתונים, אבל הסימנייה פשוט נשארת שם עד שהטרנזקציה מסתיימת.
  • השמות לא חייבים להיות ייחודיים. אם מציבים SAVEPOINT s פעמיים, ROLLBACK TO s מוצא את האחרון. שימושי לרקורסיה, מבלבל אם זה קרה בטעות.

הבא: Views

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

שאלות נפוצות

מה זה savepoint ב-SQLite?

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

מה ההבדל בין savepoint לטרנזקציה ב-SQLite?

טרנזקציה מתחילה ב-BEGIN ומסתיימת ב-COMMIT או ב-ROLLBACK. Savepoint מוצב בתוך טרנזקציה עם SAVEPOINT name ונותן נקודת ביטול חלקית. חזרה ל-savepoint לא מסיימת את הטרנזקציה העוטפת: אפשר להמשיך לעבוד ולבצע commit מאוחר יותר.

האם אפשר לקנן savepoints ב-SQLite?

כן. אפשר לערום savepoints עם שמות שונים, ו-ROLLBACK TO outer מבטל את כל מה שנעשה עד הרמה הזו, כולל savepoints פנימיים. השמות לא חייבים להיות ייחודיים: SQLite משתמשת ב-savepoint האחרון עם השם הזה, וזו התנהגות המחסנית הסטנדרטית.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל