עבודה עם שחזור בנקודת זמן (PITR)

בדף הזה מוסבר איך להשתמש בשחזור לנקודת זמן (PITR) כדי לשמור ולשחזר נתונים ב-Cloud Firestore.

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

הרשאות

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

  • בעלים של Cloud Datastore ‏ (roles/datastore.owner)

לתפקידים בהתאמה אישית, מוודאים שההרשאות הבאות ניתנות:

  • כדי להפעיל PITR כשיוצרים מסד נתונים: datastore.databases.create
  • כדי לעדכן את ההגדרות של PITR במסד נתונים קיים: datastore.databases.update,datastore.databases.list
  • כדי לבצע קריאות מנתוני PITR: datastore.databases.get,datastore.entities.get,datastore.entities.list
  • כדי לייצא נתונים של PITR: datastore.databases.export
  • כדי לייבא נתונים של PITR: datastore.databases.import
  • כדי לשכפל מסד נתונים: datastore.databases.clone

לפני שמתחילים

לפני שמתחילים להשתמש ב-PITR, חשוב לשים לב לנקודות הבאות:

  • אי אפשר להתחיל לקרוא מנקודה לפני שבעה ימים מיד אחרי שמפעילים PITR.
  • אם רוצים להפעיל PITR כשיוצרים מסד נתונים, צריך להשתמש בפקודה gcloud firestore databases create. אי אפשר להפעיל PITR בזמן יצירת מסד נתונים באמצעות מסוף Google Cloud.
  • Cloud Firestore מתחיל לשמור גרסאות מהנקודה הזו ואילך אחרי הפעלת PITR.
  • לא ניתן לקרוא נתונים של PITR בחלון PITR אחרי שמשביתים את PITR.
  • אם מפעילים מחדש את PITR מיד אחרי ההשבתה, הנתונים הקודמים של PITR כבר לא זמינים. נתוני PITR שנוצרו לפני השבתת PITR יימחקו אחרי תאריך התפוגה של PITR.
  • אם מחקתם בטעות נתונים בשעה האחרונה והתכונה PITR מושבתת, אתם יכולים לשחזר את הנתונים על ידי הפעלת התכונה PITR תוך שעה מהמחיקה.
  • כל קריאה שמתבצעת על נתוני PITR שתוקפם פג נכשלת.

הפעלת PITR

לפני שמשתמשים ב-PITR, מפעילים את החיוב בפרויקט ב-Google Cloud. אפשר להשתמש בפונקציונליות של PITR רק בפרויקטים ב-Google Cloud שבהם החיוב מופעל.

כדי להפעיל PITR למסד הנתונים:

המסוף

  1. נכנסים לדף Databases במסוף Google Cloud.

    כניסה לדף Databases

  2. בוחרים את מסד הנתונים הרצוי מרשימת מסדי הנתונים.

  3. בתפריט הניווט, לוחצים על Disaster Recovery (התאוששות מאסון).

  4. לוחצים על עריכה כדי לערוך את ההגדרות.

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

הפעלת PITR כרוכה בעלויות אחסון. מידע נוסף זמין במאמר תמחור.

כדי להשבית את PITR, מבטלים את הסימון של התיבה Enable point-in-time recovery בדף Disaster Recovery במסוף Google Cloud.

gcloud

כדי להפעיל PITR במהלך יצירת מסד הנתונים, משתמשים בפקודה --enable-ptir ובפקודה gcloud firestore databases create באופן הבא:

gcloud firestore databases create\
  --location=LOCATION\
  --database=DATABASE_ID\
  --type=firestore-native\
  --enable-pitr

מחליפים את הערכים באופן הבא:

  • LOCATION – המיקום שבו רוצים ליצור את מסד הנתונים.
  • DATABASE_ID – מוגדר למזהה מסד נתונים.

כדי להשבית את PITR, משתמשים בפקודה gcloud firestore databases update באופן הבא:

gcloud firestore databases update\
  --database=DATABASE_ID\
  --no-enable-pitr

מחליפים את הערכים באופן הבא:

  • DATABASE_ID – מוגדר למזהה מסד הנתונים או (ברירת מחדל).

קבלת תקופת השמירה והשעה של הגרסה המוקדמת ביותר

המסוף

  1. נכנסים לדף Databases במסוף Google Cloud.

    כניסה לדף Databases

  2. בוחרים את מסד הנתונים הרצוי מרשימת מסדי הנתונים.

  3. בתפריט הניווט, לוחצים על Disaster Recovery (התאוששות מאסון).

  4. בקטע הגדרות, רושמים את תקופת השמירה ואת השעה של הגרסה המוקדמת ביותר.

    • תקופת השמירה: התקופה שבה Cloud Firestore שומר את כל הגרסאות של הנתונים במסד הנתונים. הערך הוא שעה אחת כשה-PITR מושבת, ושבעה ימים כשה-PITR מופעל.
    • הזמן של הגרסה המוקדמת ביותר: חותמת הזמן המוקדמת ביותר שבה אפשר לקרוא גרסאות ישנות יותר של הנתונים בחלון PITR. הערך הזה מתעדכן כל הזמן על ידי Cloud Firestore, והוא הופך להיות לא עדכני ברגע שמבצעים שאילתה לגביו. אם אתם משתמשים בערך הזה כדי לשחזר נתונים, חשוב לקחת בחשבון את הזמן שחלף מהרגע שבו הערך נשלף ועד לרגע שבו מתחילים את השחזור.
    • שחזור מערכת מנקודה מסוימת בזמן: מוצג Enabled אם האפשרות PITR מופעלת. אם PITR מושבת, יופיע הכיתוב Disabled.

gcloud

מריצים את הפקודה gcloud firestore databases describe באופן הבא:

gcloud firestore databases describe --database=DATABASE_ID

מחליפים את DATABASE_ID במזהה מסד הנתונים או ב-'(default)'.

הפלט שיתקבל:

    appEngineIntegrationMode: ENABLED
    concurrencyMode: PESSIMISTIC
    createTime: '2021-03-24T17:02:35.234Z'
    deleteProtectionState: DELETE_PROTECTION_DISABLED
    earliestVersionTime: '2023-06-12T16:17:25.222474Z'
    etag: IIDayqOevv8CMNTvyNK4uv8C
    keyPrefix: s
    locationId: nam5
    name: projects/PROJECT_ID/databases/DATABASE_ID
    pointInTimeRecoveryEnablement: POINT_IN_TIME_RECOVERY_DISABLED
    type: FIRESTORE_NATIVE
    uid: 5230c382-dcd2-468f-8cb3-2a1acfde2b32
    updateTime: '2021-11-17T17:48:22.171180Z'
    versionRetentionPeriod: 3600s

שם,

  • earliestVersionTime: חותמת הזמן של נתוני ה-PITR המוקדמים ביותר שמאוחסנים.
  • pointInTimeRecoveryEnablement: מוצג POINT_IN_TIME_RECOVERY_ENABLED, אם PITR מופעל. אם PITR מושבת, יוצג POINT_IN_TIME_RECOVERY_DISABLED או שהשדה pointInTimeRecoveryEnablement לא יוצג.
  • versionRetentionPeriod: תקופת הזמן שבה נתוני PITR נשמרים באלפיות השנייה. הערך יכול להיות שעה אחת אם PITR מושבת, או שבעה ימים אם PITR מופעל.

קריאת נתונים של PITR

אפשר לקרוא נתונים של PITR באמצעות ספריות הלקוח, שיטות של API ל-REST או מחבר FirestoreIO Apache Beam.

ספריות לקוח

Java

כדי לקרוא נתונים של PITR, צריך להשתמש בעסקת ReadOnly. אי אפשר לציין את readTime ישירות בפעולות קריאה. מידע נוסף זמין במאמר Transactions and batched writes (טרנזקציות וכתיבות באצווה).

  Firestore firestore = 

  TransactionOptions options =
          TransactionOptions.createReadOnlyOptionsBuilder()
              .setReadTime(
                  com.google.protobuf.Timestamp.newBuilder()
                      .setSeconds(1684098540L)
                      .setNanos(0))
              .build();

  ApiFuture<Void> futureTransaction = firestore.runTransaction(
              transaction -> {
                // Does a snapshot read document lookup
                final DocumentSnapshot documentResult =
                    transaction.get(documentReference).get();

                // Executes a snapshot read query
                final QuerySnapshot queryResult =
                  transaction.get(query).get();
              },
              options);

  // Blocks on transaction to complete
  futureTransaction.get();

צומת

כדי לקרוא נתונים של PITR, צריך להשתמש בעסקת ReadOnly. אי אפשר לציין את readTime ישירות בפעולות קריאה. מידע נוסף זמין במאמר Transactions and batched writes (טרנזקציות וכתיבות באצווה).

const documentSnapshot = await firestore.runTransaction(
    updateFunction => updateFunction.get(documentRef),
    {readOnly: true, readTime: new Firestore.Timestamp(1684098540, 0)}
);

const querySnapshot = await firestore.runTransaction(
    updateFunction => updateFunction.get(query),
    {readOnly: true, readTime: new Firestore.Timestamp(1684098540, 0)}
);

API ל-REST

קריאות PITR נתמכות בכל Cloud Firestore שיטות הקריאה, שהן get,‏ list,‏ batchGet,‏ listCollectionIds,‏ listDocuments,‏ runQuery,‏ runAggregationQuery ו-partitionQuery.

כדי לבצע קריאה באמצעות שיטות REST, אפשר לנסות אחת מהאפשרויות הבאות:

  1. בבקשה של שיטת הקריאה, מעבירים את הערך readTime כחותמת זמן נתמכת של PITR בשיטה readOptions. חותמת זמן של PITR יכולה להיות חותמת זמן ברמת דיוק של מיקרו-שנייה בשעה האחרונה, או חותמת זמן של דקה שלמה לפני השעה האחרונה, אבל לא לפני earliestVersionTime.

  2. אפשר להשתמש בפרמטר readTime יחד עם השיטה BeginTransaction כחלק מטרנזקציית ReadOnly לקריאות מרובות של PITR.

Apache Beam

אפשר להשתמש במחבר Cloud FirestoreIO Apache Beam כדי לקרוא או לכתוב מסמכים במסד נתונים Cloud Firestore בקנה מידה גדול באמצעות Dataflow.

קריאות PITR נתמכות בשיטת הקריאה הבאה של מחבר ה-IO‏ Cloud Firestore. שיטות הקריאה האלה תומכות בשיטה withReadTime(@Nullable Instant readTime) שאפשר להשתמש בה לקריאות PITR:

Java

אפשר להשתמש בקוד הבא עם קוד לדוגמה של צינור עיבוד נתונים ב-Dataflow לפעולות קריאה או כתיבה בכמות גדולה. בדוגמה הזו נעשה שימוש בשיטה withReadTime(@Nullable Instant readTime) לקריאות PITR.

  Instant readTime = Instant.ofEpochSecond(1684098540L);

  PCollection<Document> documents =
      pipeline
          .apply(Create.of(collectionId))
          .apply(
              new FilterDocumentsQuery(
                  firestoreOptions.getProjectId(), firestoreOptions.getDatabaseId()))
          .apply(FirestoreIO.v1().read().runQuery().withReadTime(readTime).withRpcQosOptions(rpcQosOptions).build())
  ...

לרשימה מלאה של דוגמאות ל-readTime בצינור Dataflow, אפשר לעיין במאגר GitHub.

ייצוא וייבוא מנתוני PITR

אפשר לייצא את מסד הנתונים אל Cloud Storage מנתוני PITR באמצעות הפקודה gcloud firestore export. אפשר לייצא נתונים מ-PITR עם חותמת זמן של דקה שלמה ב-7 הימים האחרונים, אבל לא לפני earliestVersionTime. אם הנתונים כבר לא קיימים בחותמת הזמן שצוינה, פעולת הייצוא תיכשל.

פעולת הייצוא של PITR תומכת בכל המסננים, כולל ייצוא של כל המסמכים וייצוא של אוספים ספציפיים.

  1. מייצאים את מסד הנתונים ומציינים את הפרמטר snapshot-time לחותמת הזמן של השחזור שנבחר.

    gcloud

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

    gcloud firestore export gs://BUCKET_NAME_PATH \
        --snapshot-time=PITR_TIMESTAMP \
        --collection-ids=COLLECTION_IDS \
        --namespace-ids=NAMESPACE_IDS
    

    איפה,

    • BUCKET_NAME_PATH – קטגוריה תקפה של Cloud Storage עם קידומת נתיב אופציונלית שבה מאוחסנים קובצי הייצוא.
    • PITR_TIMESTAMP – חותמת זמן של PITR ברמת פירוט של דקה, למשל, 2023-05-26T10:20:00.00Z או 2023-10-19T10:30:00.00-07:00.
    • COLLECTION_IDS – רשימה של מזהי אוספים או מזהי קבוצות של אוספים, לדוגמה – 'specific-collection-group1','specific-collection-group2'.
    • NAMESPACE_IDS – רשימה של מזהי מרחבי שמות, לדוגמה – 'customer','orders'.

    לפני שמייצאים נתונים של PITR, חשוב לשים לב לנקודות הבאות:

    • מציינים את חותמת הזמן בפורמט RFC 3339. לדוגמה, 2023-05-26T10:20:00.00Z או 2023-10-19T10:30:00.00-07:00.
    • חשוב לוודא שחותמת הזמן שציינת היא חותמת זמן של דקה שלמה במהלך שבעת הימים האחרונים, אבל לא לפני earliestVersionTime. אם הנתונים כבר לא קיימים בחותמת הזמן שצוינה, נוצרת שגיאה. חותמת הזמן חייבת להיות דקה שלמה, גם אם השעה שצוינה היא בשעה האחרונה.
    • לא נחייב אתכם על ייצוא PITR שנכשל.
  2. ייבוא למסד נתונים.

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

שכפול ממסד נתונים

אפשר לשכפל מסד נתונים קיים בנקודת זמן נבחרת למסד נתונים חדש:

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

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

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

  • חותמת הזמן היא ברמת גרנולריות של דקה אחת ומציינת נקודת זמן בעבר, בתקופה שמוגדרת על ידי חלון ה-PITR:

    • אם PITR מופעל במסד הנתונים, אפשר לבחור כל דקה ב-7 הימים האחרונים (או פחות, אם PITR הופעל לפני פחות מ-7 ימים).
    • אם PITR לא מופעל, אפשר לבחור כל דקה בשעה האחרונה.
    • אפשר לבדוק את חותמת הזמן המוקדמת ביותר שאפשר לבחור בתיאור של מסד הנתונים.

המסוף

במסוף Firebase אין תמיכה בשיבוט מסדי נתונים. אפשר להשתמש בהוראות ל-Google Cloud CLI כדי לשכפל מסדי נתונים.

gcloud

משתמשים בפקודה gcloud alpha firestore databases clone כדי לשכפל מסד נתונים:

gcloud alpha firestore databases clone \
--source-database='SOURCE_DATABASE_ID' \
--snapshot-time='PITR_TIMESTAMP' \
--destination-database='DESTINATION_DATABASE_ID'

מחליפים את מה שכתוב בשדות הבאים:

  • SOURCE_DATABASE_ID: מזהה מסד נתונים של מסד נתונים קיים שרוצים לשכפל.

  • PITR_TIMESTAMP: חותמת זמן של PITR בפורמט RFC 3339, ברמת דיוק של דקה. לדוגמה: 2025-06-01T10:20:00.00Z או 2025-06-01T10:30:00.00-07:00.

  • DESTINATION_DATABASE_ID: מזהה מסד נתונים של מסד נתונים חדש ששוכפל. המזהה של מסד הנתונים לא יכול להיות משויך למסד נתונים קיים.

דוגמה:

gcloud alpha firestore databases clone \
--source-database='projects/example-project/databases/(default)' \
--snapshot-time='2025-06-01T10:20:00.00Z' \
--destination-database='projects/example-project/databases/example-dest-db'

שינוי הגדרות ההצפנה של מסד הנתונים המשוכפל

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

  • (ברירת מחדל) use-source-encryption: שימוש באותה הגדרת הצפנה כמו במסד הנתונים של המקור.
  • google-default-encryption: שימוש בהצפנה שמוגדרת כברירת מחדל ב-Google.
  • customer-managed-encryption: שימוש בהצפנת CMEK. מציינים מזהה מפתח בארגומנט --kms-key-name.

בדוגמה הבאה מוצג איך להגדיר הצפנה באמצעות CMEK למסד הנתונים המשוכפל:

gcloud alpha firestore databases clone \
--source-database='projects/example-project/databases/(default)' \
--snapshot-time='2025-06-01T10:20:00.00Z' \
--destination-database='projects/example-project/databases/example-dest-db' \
--encryption-type='customer-managed-encryption' \
--kms-key-name='projects/example-project/locations/us-central1/keyRings/example-key-ring/cryptoKeys/example-key'