יכולת סריאליזציה ובידוד של עסקאות

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

טרנזקציות ותחרות על נתונים

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

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

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

ABORTED: Too much contention on these documents. Please try again.

ההחלטה איזו פעולה תיכשל או תתעכב תלויה בסוג של בקרת הבו-זמניות.

בקרת בו-זמניות

מצב בו-זמניות הוא אפשרות של מסד נתונים שניתן להגדיר. ‫Cloud Firestore תומך במצבי בו-זמניות הבאים:

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

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

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

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

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

הגדרות ברירת המחדל של מצב בו-זמניות (concurrency)

ברירת המחדל במהדורת Standard היא PESSIMISTIC. ברירת המחדל במהדורת Enterprise היא OPTIMISTIC. עם זאת, ההתנהגות תלויה גם בסוג ספריית הלקוח:

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

מצב צפייה בו-זמנית

מריצים את הפקודה gcloud firestore databases describe כדי לראות את מצב בו-זמניות בצד השרת של מסד הנתונים:

gcloud firestore databases describe \
  --project=PROJECT_ID \
  --database=DATABASE_ID

שינוי מצב בו-זמניות

מריצים את הפקודה gcloud firestore databases update כדי לשנות את מצב בו-זמניות בצד השרת של מסד הנתונים:

gcloud firestore databases update \
  --project=PROJECT_ID \
  --database=DATABASE_ID \
  --concurrency-mode=CONCURRENCY_MODE

כאשר:

  • ‫CONCURRENCY_MODE הוא PESSIMISTIC או OPTIMISTIC.
  • ‫PROJECT_ID הוא המזהה של פרויקט Google Cloud.
  • ‫DATABASE_ID הוא המזהה של מסד הנתונים ב-Cloud Firestore.

תחרות על נתונים בערכות ה-SDK לנייד ולאינטרנט

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

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

תחרות על נתונים בספריות הלקוח של השרת

ספריות לקוח של שרת (C#‎,‏ Go, ‏ Java, ‏ Node.js, ‏ PHP, ‏ Python, ‏ Ruby) משתמשות בתכונה טרנזקציות מובנות. הטרנזקציות האלה משתמשות בהגדרת מצב בו-זמניות ברמת מסד הנתונים, וברירת המחדל תלויה במהדורה:

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

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

בידוד שמאפשר סריאליזציה

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

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

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

בידוד שניתן לסדרתיות מגדיר את רמת הבידוד הגבוהה ביותר. בידוד שניתן להפוך לסדרתי (serializable) אומר ש:

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

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

‫Cloud Firestore מבטיח בידוד של טרנזקציות שניתן להפוך אותן לסדרתיות. העסקאות ב-Cloud Firestore עוברות סריאליזציה ומבודדות לפי זמן האישור.

בידוד שמאפשר סריאליזציה לפי זמן השמירה

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

ביצוע העסקה בפועל נמשך זמן מה. הביצוע של טרנזקציה מתחיל לפני זמן ה-commit, והביצוע של כמה פעולות יכול לחפוף. ‫Cloud Firestore תומך בבידוד שמאפשר סריאליזציה ומבטיח ש:

  • ‫Cloud Firestore מבצע טרנזקציות לפי סדר זמן הביצוע.
  • Cloud Firestore מבודד עסקאות מפעולות בו-זמניות עם זמן אישור מאוחר יותר.

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

בידוד בתוך עסקה

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

בעיות שקשורות לתחרות על נתונים

מידע נוסף על מאבקי נתונים ואיך לפתור אותם זמין בדף פתרון הבעיות.