עסקה היא פעולה או קבוצה של פעולות שמובטח שהן אטומיות, כלומר אף פעם לא מוחלות רק חלק מהעסקאות. כל הפעולות בעסקה מוחלות, או שאף אחת מהן לא מוחלת. העסקאות מוגבלות למשך זמן מקסימלי של 60 שניות, עם פסק זמן של 10 שניות אחרי 30 שניות.
באמצעות NDB asynchronous API,
an application can manage multiple
transactions simultaneously if they are independent.
ה-API הסינכרוני מציע API פשוט יותר באמצעות הדקורטור @ndb.transactional().
הפונקציה המקושטת מופעלת בהקשר של העסקה.
אם העסקה מתנגשת עם עסקה אחרת, היא נכשלת. NDB מנסה לבצע שוב באופן אוטומטי עסקאות שנכשלו כמה פעמים.
יכול להיות שהפונקציה תופעל כמה פעמים אם המערכת תנסה לבצע את העסקה שוב. יש מגבלה (ברירת המחדל היא 3) על מספר הניסיונות החוזרים. אם העסקה עדיין לא מצליחה, NDB מעלה את TransactionFailedError. אפשר לשנות את מספר הניסיונות החוזרים על ידי העברת retries=N אל הדקורטור transactional().
מספר הניסיונות הוא 0, כלומר המערכת מנסה לבצע את העסקה פעם אחת, אבל לא מנסה שוב אם היא נכשלת. מספר הניסיונות הוא N, כלומר המערכת מנסה לבצע את העסקה N+1 פעמים. דוגמה:
בעסקאות, מותרות רק שאילתות של צאצאים. כברירת מחדל, טרנזקציה יכולה לפעול רק עם ישויות באותה קבוצת ישויות (ישויות שהמפתחות שלהן כוללים את אותה 'ישות אם').
אפשר לציין עסקאות חוצות-קבוצות (XG) (שמאפשרות עד עשרים וחמש קבוצות ישויות), על ידי העברת xg=True:
עסקאות חוצות-קבוצות פועלות על פני כמה קבוצות ישויות, והן מתנהגות כמו עסקאות של קבוצה אחת, אבל הן לא נכשלות אם הקוד מנסה לעדכן ישויות מיותר מקבוצת ישויות אחת.
אם הפונקציה מעלה חריגה, העסקה מבוטלת באופן מיידי ו-NDB מעלה מחדש את החריגה כדי שהקוד שקורא לה יראה אותה.
אפשר לאלץ עסקה להיכשל בלי להציג הודעה על כך על ידי העלאת החריגה ndb.Rollback (קריאת הפונקציה מחזירה None במקרה הזה). אין מנגנון שמאלץ ניסיון חוזר.
יכול להיות שיש לכם פונקציה שאתם לא רוצים להפעיל תמיד בעסקה. במקום להוסיף את @ndb.transactional לפונקציה כזו, מעבירים אותה כפונקציית קריאה חוזרת ל-ndb.transaction().
כדי לבדוק אם קטע קוד מסוים פועל בתוך טרנזקציה, משתמשים בפונקציה in_transaction().
אפשר לציין איך פונקציה 'טרנזקציונלית' צריכה להתנהג אם היא מופעלת על ידי קוד שכבר נמצא בטרנזקציה. הדקורטור @ndb.non_transactional מציין שפונקציה לא צריכה לפעול בטרנזקציה. אם היא מופעלת בטרנזקציה, היא פועלת מחוץ לטרנזקציה. הדקורטור @ndb.transactional והפונקציה ndb.transaction מקבלים ארגומנט של מילת המפתח propagation. לדוגמה, אם פונקציה
צריכה להתחיל טרנזקציה חדשה ועצמאית, צריך להוסיף לה את העיטור הבא:
סוגי ההפצה מופיעים עם אפשרויות ההקשר ואפשרויות העסקה האחרות
ההתנהגות של העסקאות וההתנהגות של המטמון של NDB יכולות לגרום לבלבול אם לא יודעים מה קורה. אם משנים ישות בתוך טרנזקציה אבל עדיין לא מבצעים commit של הטרנזקציה, במטמון ההקשר של NDB יש את הערך ששונה, אבל במאגר הנתונים הבסיסי עדיין יש את הערך שלא שונה.
הוספה לתור של משימות טרנזקציונליות
אפשר להוסיף משימה לתור כחלק מטרנזקציית Datastore, כך שהמשימה תתווסף לתור רק אם הטרנזקציה תאושר בהצלחה. אם העסקה לא תאושר, המשימה לא תתווסף לתור. אם העסקה תאושר, המשימה תתווסף לתור. אחרי שהמשימה מתווספת לתור, היא לא מבוצעת באופן מיידי, ולכן היא לא אטומית לעסקה. עם זאת, אחרי שהמשימה מתווספת לתור, המערכת תנסה לבצע אותה שוב ושוב עד שהיא תצליח. ההגדרה הזו חלה על כל משימה שמוכנסת לתור במהלך פונקציה עם קישוט.
משימות טרנזקציונליות שימושיות כי הן מאפשרות לכם לשלב פעולות שאינן Datastore בטרנזקציה שתלויה בהצלחת הטרנזקציה (למשל, שליחת אימייל לאישור רכישה). אפשר גם לקשר פעולות ב-Datastore לעסקה, למשל לבצע שינויים בקבוצות של ישויות מחוץ לעסקה רק אם העסקה מצליחה.
אפליקציה לא יכולה להוסיף יותר מחמישה משימות טרנזקציונליות לתורי משימות במהלך טרנזקציה אחת. למשימות טרנזקציונליות אסור להכיל שמות שצוינו על ידי המשתמש.