עסקאות

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

שימוש בעסקאות

תוקף העסקאות פג אחרי 270 שניות או אם לא מתבצעת פעילות במשך 60 שניות.

פעולה עלולה להיכשל במקרים הבאים:

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

בכל המקרים האלה, ה-API של Datastore מחזיר שגיאה.

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

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

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

C#

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore C# API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

private void TransferFunds(Key fromKey, Key toKey, long amount)
{
    using (var transaction = _db.BeginTransaction())
    {
        var entities = transaction.Lookup(fromKey, toKey);
        entities[0]["balance"].IntegerValue -= amount;
        entities[1]["balance"].IntegerValue += amount;
        transaction.Update(entities);
        transaction.Commit();
    }
}

Go

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Go API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

type BankAccount struct {
	Balance int
}

const amount = 50
keys := []*datastore.Key{to, from}
tx, err := client.NewTransaction(ctx)
if err != nil {
	log.Fatalf("client.NewTransaction: %v", err)
}
accs := make([]BankAccount, 2)
if err := tx.GetMulti(keys, accs); err != nil {
	tx.Rollback()
	log.Fatalf("tx.GetMulti: %v", err)
}
accs[0].Balance += amount
accs[1].Balance -= amount
if _, err := tx.PutMulti(keys, accs); err != nil {
	tx.Rollback()
	log.Fatalf("tx.PutMulti: %v", err)
}
if _, err = tx.Commit(); err != nil {
	log.Fatalf("tx.Commit: %v", err)
}

Java

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Java API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

void transferFunds(Key fromKey, Key toKey, long amount) {
  Transaction txn = datastore.newTransaction();
  try {
    List<Entity> entities = txn.fetch(fromKey, toKey);
    Entity from = entities.get(0);
    Entity updatedFrom =
        Entity.newBuilder(from).set("balance", from.getLong("balance") - amount).build();
    Entity to = entities.get(1);
    Entity updatedTo =
        Entity.newBuilder(to).set("balance", to.getLong("balance") + amount).build();
    txn.put(updatedFrom, updatedTo);
    txn.commit();
  } finally {
    if (txn.isActive()) {
      txn.rollback();
    }
  }
}

Node.js

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Node.js API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

async function transferFunds(fromKey, toKey, amount) {
  const transaction = datastore.transaction();
  await transaction.run();
  const results = await Promise.all([
    transaction.get(fromKey),
    transaction.get(toKey),
  ]);
  const accounts = results.map(result => result[0]);

  accounts[0].balance -= amount;
  accounts[1].balance += amount;

  transaction.save([
    {
      key: fromKey,
      data: accounts[0],
    },
    {
      key: toKey,
      data: accounts[1],
    },
  ]);

  return await transaction.commit();
}

PHP

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore PHP API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

/**
 * Update two entities in a transaction.
 *
 * @param string $fromKeyId
 * @param string $toKeyId
 * @param int $amount
 * @param string $namespaceId
 */
function transfer_funds(
    string $fromKeyId,
    string $toKeyId,
    int $amount,
    string $namespaceId = null
) {
    $datastore = new DatastoreClient(['namespaceId' => $namespaceId]);
    $transaction = $datastore->transaction();
    $fromKey = $datastore->key('Account', $fromKeyId);
    $toKey = $datastore->key('Account', $toKeyId);
    // The option 'sort' is important here, otherwise the order of the result
    // might be different from the order of the keys.
    $result = $transaction->lookupBatch([$fromKey, $toKey], ['sort' => true]);
    if (count($result['found']) != 2) {
        $transaction->rollback();
    }
    $fromAccount = $result['found'][0];
    $toAccount = $result['found'][1];
    $fromAccount['balance'] -= $amount;
    $toAccount['balance'] += $amount;
    $transaction->updateBatch([$fromAccount, $toAccount]);
    $transaction->commit();
}

Python

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Python API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

def transfer_funds(client, from_key, to_key, amount):
    with client.transaction():
        from_account = client.get(from_key)
        to_account = client.get(to_key)

        from_account["balance"] -= amount
        to_account["balance"] += amount

        client.put_multi([from_account, to_account])

Ruby

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Ruby API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

def transfer_funds from_key, to_key, amount
  datastore.transaction do |tx|
    from = tx.find from_key
    from["balance"] -= amount
    to = tx.find to_key
    to["balance"] += amount
    tx.save from, to
  end
end

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

מה אפשר לעשות בעסקה

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

בידוד ועקביות

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

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

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

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

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

‫Firestore במצב Datastore תומך בשלושה מצבי מקביליות. מצב הריצה המקבילית הוא הגדרה במסד הנתונים שקובעת איך אינטראקציות של טרנזקציות מקבילות מתבצעות. אפשר לבחור באחד ממצבי הריצה המקבילית הבאים:

  • פסימיות

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

    כברירת מחדל, מסדי נתונים של Firestore במצב Datastore משתמשים במצב מקביליות פסימי.

  • אופטימיסטי

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

  • אופטימיות עם קבוצות ישויות

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

    • העסקאות מוגבלות ל-25 קבוצות ישויות.
    • הכתיבה לקבוצת ישויות מוגבלת ל-1 בשנייה.
    • שאילתות בעסקאות חייבות להיות שאילתות אב.

    כדי להסיר את המגבלות על השאילתות, הטרנזקציות והתפוקה של פעולות הכתיבה של OPTIMISTIC_WITH_ENTITY_GROUPS, צריך לשנות את מצב הבו-זמניות (concurrency) של הפרויקט ל'אופטימי'. כדי לוודא שהשינוי הזה תואם לפרויקט שלכם:

    1. יוצרים פרויקט בדיקה ב-Firestore במצב Datastore.

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

    3. מריצים בדיקות בפרויקט הבדיקה כדי לוודא שעומס העבודה פועל כצפוי בלי קבוצות ישויות.

    4. שינוי מצב הריצה המקבילית של הפרויקט הראשי מ-OPTIMISTIC_WITH_ENTITY_GROUPS ל-OPTIMISTIC.

    כדי להמשיך להשתמש בספרייה הזו.

הצגת מצב ההפעלה בו-זמנית

מריצים את הפקודה 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

where:

  • CONCURRENCY_MODE הוא PESSIMISTIC,‏ OPTIMISTIC או OPTIMISTIC_WITH_ENTITY_GROUPS.
  • PROJECT_ID הוא מזהה הפרויקט. Google Cloud
  • DATABASE_ID הוא המזהה של מסד הנתונים במצב Datastore.

שימושים בעסקאות

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

C#

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore C# API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

/// <summary>
/// Retry the action when a Grpc.Core.RpcException is thrown.
/// </summary>
private T RetryRpc<T>(Func<T> action)
{
    List<Grpc.Core.RpcException> exceptions = null;
    var delayMs = _retryDelayMs;
    for (int tryCount = 0; tryCount < _retryCount; ++tryCount)
    {
        try
        {
            return action();
        }
        catch (Grpc.Core.RpcException e)
        {
            if (exceptions == null)
                exceptions = new List<Grpc.Core.RpcException>();
            exceptions.Add(e);
        }
        System.Threading.Thread.Sleep(delayMs);
        delayMs *= 2;  // Exponential back-off.
    }
    throw new AggregateException(exceptions);
}

private void RetryRpc(Action action)
{
    RetryRpc(() => { action(); return 0; });
}

[Fact]
public void TestTransactionalRetry()
{
    int tryCount = 0;
    var keys = UpsertBalances();
    RetryRpc(() =>
    {
        using (var transaction = _db.BeginTransaction())
        {
            TransferFunds(keys[0], keys[1], 10, transaction);
            // Insert a conflicting transaction on the first try.
            if (tryCount++ == 0)
                TransferFunds(keys[1], keys[0], 5);
            transaction.Commit();
        }
    });
    Assert.Equal(2, tryCount);
}

Go

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Go API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

type BankAccount struct {
	Balance int
}

const amount = 50
_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
	keys := []*datastore.Key{to, from}
	accs := make([]BankAccount, 2)
	if err := tx.GetMulti(keys, accs); err != nil {
		return err
	}
	accs[0].Balance += amount
	accs[1].Balance -= amount
	_, err := tx.PutMulti(keys, accs)
	return err
})

Java

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Java API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

int retries = 5;
while (true) {
  try {
    transferFunds(fromKey, toKey, 10);
    break;
  } catch (DatastoreException e) {
    if (retries == 0) {
      throw e;
    }
    --retries;
  }
}
// Retry handling can also be configured and automatically applied using google-cloud-java.

Node.js

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Node.js API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

async function transferFundsWithRetry() {
  const maxTries = 5;

  async function tryRequest(currentAttempt, delay) {
    try {
      await transferFunds(fromKey, toKey, 10);
    } catch (err) {
      if (currentAttempt <= maxTries) {
        // Use exponential backoff
        setTimeout(async () => {
          await tryRequest(currentAttempt + 1, delay * 2);
        }, delay);
      }
      throw err;
    }
  }

  await tryRequest(1, 100);
}

PHP

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore PHP API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

$retries = 5;
for ($i = 0; $i < $retries; $i++) {
    try {
        require_once __DIR__ . '/transfer_funds.php';
        transfer_funds($fromKeyId, $toKeyId, 10, $namespaceId);
    } catch (\Google\Cloud\Core\Exception\ConflictException $e) {
        // if $i >= $retries, the failure is final
        continue;
    }
    // Succeeded!
    break;
}

Python

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Python API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

import google.cloud.exceptions

for _ in range(5):
    try:
        transfer_funds(client, account1.key, account2.key, 50)
        break
    except google.cloud.exceptions.Conflict:
        continue
else:
    print("Transaction failed.")

Ruby

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Ruby API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

(1..5).each do |i|
  begin
    return transfer_funds from_key, to_key, amount
  rescue Google::Cloud::Error => e
    raise e if i == 5
  end
end

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

שימוש נפוץ נוסף בעסקאות הוא אחזור של ישות עם מפתח בעל שם, או יצירה של ישות כזו אם היא עדיין לא קיימת (הדוגמה הזו מבוססת על הדוגמה של TaskList מתוך יצירת ישות):

C#

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore C# API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Entity task;
using (var transaction = _db.BeginTransaction())
{
    task = transaction.Lookup(_sampleTask.Key);
    if (task == null)
    {
        transaction.Insert(_sampleTask);
        transaction.Commit();
    }
}

Go

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Go API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
	var task Task
	if err := tx.Get(key, &task); err != datastore.ErrNoSuchEntity {
		return err
	}
	_, err := tx.Put(key, &Task{
		Category:    "Personal",
		Done:        false,
		Priority:    4,
		Description: "Learn Cloud Datastore",
	})
	return err
})

Java

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Java API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Entity task;
Transaction txn = datastore.newTransaction();
try {
  task = txn.get(taskKey);
  if (task == null) {
    task = Entity.newBuilder(taskKey).build();
    txn.put(task);
    txn.commit();
  }
} finally {
  if (txn.isActive()) {
    txn.rollback();
  }
}

Node.js

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Node.js API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

async function getOrCreate(taskKey, taskData) {
  const taskEntity = {
    key: taskKey,
    data: taskData,
  };
  const transaction = datastore.transaction();

  try {
    await transaction.run();
    const [task] = await transaction.get(taskKey);
    if (task) {
      // The task entity already exists.
      await transaction.rollback();
    } else {
      // Create the task entity.
      transaction.save(taskEntity);
      await transaction.commit();
    }
    return taskEntity;
  } catch (err) {
    await transaction.rollback();
  }
}

PHP

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore PHP API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

$transaction = $datastore->transaction();
$entity = $transaction->lookup($task->key());
if ($entity === null) {
    $entity = $transaction->insert($task);
    $transaction->commit();
}

Python

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Python API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

import datetime

with client.transaction():
    key = client.key(
        "Task", datetime.datetime.now(tz=datetime.timezone.utc).isoformat()
    )

    task = client.get(key)

    if not task:
        task = datastore.Entity(key)
        task.update({"description": "Example task"})
        client.put(task)

    return task

Ruby

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Ruby API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

task = nil
datastore.transaction do |tx|
  task = tx.find task_key
  if task.nil?
    task = datastore.entity task_key do |t|
      t["category"] = "Personal"
      t["done"] = false
      t["priority"] = 4
      t["description"] = "Learn Cloud Datastore"
    end
    tx.save task
  end
end

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

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

עסקאות עם הרשאת קריאה בלבד

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

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

C#

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore C# API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Entity taskList;
IReadOnlyList<Entity> tasks;
using (var transaction = _db.BeginTransaction(TransactionOptions.CreateReadOnly()))
{
    taskList = transaction.Lookup(taskListKey);
    var query = new Query("Task")
    {
        Filter = Filter.HasAncestor(taskListKey)
    };
    tasks = transaction.RunQuery(query).Entities;
    transaction.Commit();
}

Go

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Go API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

tx, err := client.NewTransaction(ctx, datastore.ReadOnly)
if err != nil {
	log.Fatalf("client.NewTransaction: %v", err)
}
defer tx.Rollback() // Transaction only used for read.

ancestor := datastore.NameKey("TaskList", "default", nil)
query := datastore.NewQuery("Task").Ancestor(ancestor).Transaction(tx)
var tasks []Task
_, err = client.GetAll(ctx, query, &tasks)

Java

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Java API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

Entity taskList;
QueryResults<Entity> tasks;
Transaction txn =
    datastore.newTransaction(
        TransactionOptions.newBuilder().setReadOnly(ReadOnly.newBuilder().build()).build());
try {
  taskList = txn.get(taskListKey);
  Query<Entity> query =
      Query.newEntityQueryBuilder()
          .setKind("Task")
          .setFilter(PropertyFilter.hasAncestor(taskListKey))
          .build();
  tasks = txn.run(query);
  txn.commit();
} finally {
  if (txn.isActive()) {
    txn.rollback();
  }
}

Node.js

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Node.js API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

async function getTaskListEntities() {
  const transaction = datastore.transaction({readOnly: true});
  try {
    const taskListKey = datastore.key(['TaskList', 'default']);

    await transaction.run();
    const [taskList] = await transaction.get(taskListKey);
    const query = datastore.createQuery('Task').hasAncestor(taskListKey);
    const [taskListEntities] = await transaction.runQuery(query);
    await transaction.commit();
    return [taskList, taskListEntities];
  } catch (err) {
    await transaction.rollback();
  }
}

PHP

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore PHP API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

$transaction = $datastore->readOnlyTransaction();
$taskListKey = $datastore->key('TaskList', 'default');
$query = $datastore->query()
    ->kind('Task')
    ->hasAncestor($taskListKey);
$result = $transaction->runQuery($query);
$taskListEntities = [];
$num = 0;
/* @var Entity $task */
foreach ($result as $task) {
    $taskListEntities[] = $task;
    $num += 1;
}

Python

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Python API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

with client.transaction(read_only=True):
    task_list_key = client.key("TaskList", "default")

    task_list = client.get(task_list_key)

    query = client.query(kind="Task", ancestor=task_list_key)
    tasks_in_list = list(query.fetch())

    return task_list, tasks_in_list

Ruby

מידע על התקנת ספריית הלקוח של Cloud Datastore ושימוש בה מופיע במאמר ספריות הלקוח של Cloud Datastore. מידע נוסף מופיע במאמרי העזרה של Cloud Datastore Ruby API.

כדי לבצע אימות ב-Cloud Datastore, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לסביבת פיתוח מקומית.

# task_list_name = "default"
task_list_key = datastore.key "TaskList", task_list_name
datastore.read_only_transaction do |tx|
  task_list = tx.find task_list_key
  query = datastore.query("Task").ancestor(task_list)
  tasks_in_list = tx.run query
end

המאמרים הבאים