A transaction is a set of operations on one or more entities. Each transaction is guaranteed to be atomic, meaning that transactions are never partially applied. Either all of the operations in the transaction are applied, or none of them are applied.
Using transactions
Transactions expire after 270 seconds or if idle for 60 seconds.
An operation may fail when:
- Too many concurrent modifications are attempted on the same entity.
- The transaction exceeds a resource limit.
- The Datastore mode database encounters an internal error.
In all these cases, the Datastore API returns an error.
Transactions are an optional feature. You're not required to use transactions to perform database operations.
An application can execute a set of statements and operations in a single transaction, such that if any statement or operation raises an exception, none of the database operations in the set are applied. The application defines the actions to perform in the transaction.
The following snippet shows how to perform a transaction. It transfers money from one account to another.
C#
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore C# API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Go
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Go API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Java
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Java API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Node.js
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Node.js API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
PHP
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore PHP API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Python
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Python API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Ruby
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Ruby API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Note that in order to keep our examples more succinct we sometimes omit the rollback
if the transaction fails. In production code, it is important to ensure that every transaction is either explicitly committed or rolled back.
What can be done in a transaction
Transactions can query or lookup any number of entities. The maximum size of a transaction is 10 MiB. You can use a read-write transaction or a read-only transaction.
Isolation and consistency
Datastore mode databases enforce serializable isolation. Data read or modified by a transaction cannot be concurrently modified.
Queries and lookups in a transaction see a consistent snapshot of the state of the database. This snapshot is guaranteed to contain the effect of all transactions and writes that completed prior to the beginning of the transaction.
This consistent snapshot view also extends to reads after writes inside transactions. Unlike with most databases, queries and lookups inside a Datastore mode transaction do not see the results of previous writes inside that transaction. Specifically, if an entity is modified or deleted within a transaction, a query or lookup returns the original version of the entity as of the beginning of the transaction, or nothing if the entity did not exist then.
Outside of transactions, queries and lookups also have serializable isolation.
Concurrency modes
Firestore in Datastore mode supports three concurrency modes. The concurrency mode is a database setting that determines how concurrent transactions interact. You can select from one of the following concurrency modes:
Pessimistic
Read-write transactions use reader/writer locks to enforce isolation and serializability. When two or more concurrent read-write transactions read or write the same data, the lock held by one transaction can delay the other transactions. If your transaction does not require any writes, you can improve performance and avoid contention with other transactions by using a read-only transaction. Read-only transaction do not require any locks.
Firestore in Datastore mode databases use the pessimistic concurrency mode by default.
Optimistic
When two or more concurrent read-write transactions read or write the same data, only the first transaction to commit its changes succeeds. Other transactions that perform writes fail on commit.
Optimistic With Entity Groups
Use this concurrency mode only if your app depends on the entity group transactional semantics of legacy Cloud Datastore. This concurrency mode places additional limits on transactions:
- Transactions are limited to 25 entity groups.
- Writes to an entity group are limited to 1 per second.
- Queries in transactions must be ancestor queries.
To remove
OPTIMISTIC_WITH_ENTITY_GROUPS
query, transaction and write throughput limitations, change your project's concurrency mode to Optimistic. To ensure this change is compatible with your project:Create a test project in Firestore in Datastore mode.
Change the test project's concurrency mode to
OPTIMISTIC
. Issue an HTTP PATCH request, as demonstrated below.Run tests on the test project to ensure that you workload performs as expected without Entity Groups.
Change your main project's concurrency mode from
OPTIMISTIC_WITH_ENTITY_GROUPS
toOPTIMISTIC
.
View concurrency mode
Use the Firestore projects.databases REST resource to view your database's concurrency mode:
curl -X GET -H "Authorization: Bearer "$(gcloud auth print-access-token) \
"https://firestore.googleapis.com/v1/projects/PROJECT_ID/databases"
Change concurrency mode
To change your database's concurrency mode, send a PATCH
request to the Firestore
projects.databases
REST resource:
curl --request PATCH \
--header "Authorization: Bearer "$(gcloud auth print-access-token) \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"concurrencyMode":"CONCURRENCY_MODE"}' \
"https://firestore.googleapis.com/v1/projects/PROJECT_ID/databases/(default)?updateMask=concurrencyMode"
where:
- CONCURRENCY_MODE is
PESSIMISTIC
,OPTIMISTIC
, orOPTIMISTIC_WITH_ENTITY_GROUPS
. - PROJECT_ID is the ID of your Google Cloud project.
Uses for transactions
One use of transactions is updating an entity with a new property value relative
to its current value. The transferFunds
example above does that for two
entities, by withdrawing money from one account and transferring it to another.
The Datastore API does not automatically retry transactions, but you
can add your own logic to retry them, for instance to handle conflicts when
another request updates the same entity at the same time.
C#
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore C# API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Go
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Go API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Java
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Java API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Node.js
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Node.js API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
PHP
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore PHP API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Python
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Python API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Ruby
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Ruby API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
This requires a transaction because the value of balance
in an entity may be updated by another user after this code fetches the object, but before it saves the modified object. Without a transaction, the user's request uses the value of balance
prior to the other user's update, and the save overwrites the new value. With a
transaction, the application is told about the other user's update.
Another common use for transactions is to fetch an entity with a named key, or create it if it doesn't yet exist (this example builds on the TaskList example from creating an entity):
C#
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore C# API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Go
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Go API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Java
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Java API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Node.js
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Node.js API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
PHP
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore PHP API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Python
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Python API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Ruby
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Ruby API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
As before, a transaction is necessary to handle the case where another user is attempting to create or update an entity with the same string ID. Without a transaction, if the entity does not exist and two users attempt to create it, the second overwrites the first without knowing that it happened.
When a transaction fails, you can have your app retry the transaction until it succeeds, or you can let your users deal with the error by propagating it to your app's user interface level. You do not have to create a retry loop around every transaction.
Read-only transactions
Finally, you can use a transaction to read a consistent snapshot of the database. This can be useful when you need multiple reads to render a page or to export data that must be consistent. You can create read-only transaction for these cases.
Read-only transactions cannot modify entities, but in return, they do not contend with any other transactions and do not need to be retried. If you perform only reads in a regular, read-write transaction, then that transaction may contend with transaction that modify the same data.
C#
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore C# API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Go
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Go API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Java
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Java API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Node.js
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Node.js API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
PHP
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore PHP API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Python
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Python API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
Ruby
To learn how to install and use the client library for Cloud Datastore, see Cloud Datastore client libraries. For more information, see the Cloud Datastore Ruby API reference documentation.
To authenticate to Cloud Datastore, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.
What's next
- Learn about Queries.