xref: /aosp_15_r20/external/googleapis/google/spanner/v1/transaction.proto (revision d5c09012810ac0c9f33fe448fb6da8260d444cc9)
1// Copyright 2023 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15syntax = "proto3";
16
17package google.spanner.v1;
18
19import "google/protobuf/duration.proto";
20import "google/protobuf/timestamp.proto";
21
22option csharp_namespace = "Google.Cloud.Spanner.V1";
23option go_package = "cloud.google.com/go/spanner/apiv1/spannerpb;spannerpb";
24option java_multiple_files = true;
25option java_outer_classname = "TransactionProto";
26option java_package = "com.google.spanner.v1";
27option php_namespace = "Google\\Cloud\\Spanner\\V1";
28option ruby_package = "Google::Cloud::Spanner::V1";
29
30// Transactions:
31//
32// Each session can have at most one active transaction at a time (note that
33// standalone reads and queries use a transaction internally and do count
34// towards the one transaction limit). After the active transaction is
35// completed, the session can immediately be re-used for the next transaction.
36// It is not necessary to create a new session for each transaction.
37//
38// Transaction modes:
39//
40// Cloud Spanner supports three transaction modes:
41//
42//   1. Locking read-write. This type of transaction is the only way
43//      to write data into Cloud Spanner. These transactions rely on
44//      pessimistic locking and, if necessary, two-phase commit.
45//      Locking read-write transactions may abort, requiring the
46//      application to retry.
47//
48//   2. Snapshot read-only. Snapshot read-only transactions provide guaranteed
49//      consistency across several reads, but do not allow
50//      writes. Snapshot read-only transactions can be configured to read at
51//      timestamps in the past, or configured to perform a strong read
52//      (where Spanner will select a timestamp such that the read is
53//      guaranteed to see the effects of all transactions that have committed
54//      before the start of the read). Snapshot read-only transactions do not
55//      need to be committed.
56//
57//      Queries on change streams must be performed with the snapshot read-only
58//      transaction mode, specifying a strong read. Please see
59//      [TransactionOptions.ReadOnly.strong][google.spanner.v1.TransactionOptions.ReadOnly.strong]
60//      for more details.
61//
62//   3. Partitioned DML. This type of transaction is used to execute
63//      a single Partitioned DML statement. Partitioned DML partitions
64//      the key space and runs the DML statement over each partition
65//      in parallel using separate, internal transactions that commit
66//      independently. Partitioned DML transactions do not need to be
67//      committed.
68//
69// For transactions that only read, snapshot read-only transactions
70// provide simpler semantics and are almost always faster. In
71// particular, read-only transactions do not take locks, so they do
72// not conflict with read-write transactions. As a consequence of not
73// taking locks, they also do not abort, so retry loops are not needed.
74//
75// Transactions may only read-write data in a single database. They
76// may, however, read-write data in different tables within that
77// database.
78//
79// Locking read-write transactions:
80//
81// Locking transactions may be used to atomically read-modify-write
82// data anywhere in a database. This type of transaction is externally
83// consistent.
84//
85// Clients should attempt to minimize the amount of time a transaction
86// is active. Faster transactions commit with higher probability
87// and cause less contention. Cloud Spanner attempts to keep read locks
88// active as long as the transaction continues to do reads, and the
89// transaction has not been terminated by
90// [Commit][google.spanner.v1.Spanner.Commit] or
91// [Rollback][google.spanner.v1.Spanner.Rollback]. Long periods of
92// inactivity at the client may cause Cloud Spanner to release a
93// transaction's locks and abort it.
94//
95// Conceptually, a read-write transaction consists of zero or more
96// reads or SQL statements followed by
97// [Commit][google.spanner.v1.Spanner.Commit]. At any time before
98// [Commit][google.spanner.v1.Spanner.Commit], the client can send a
99// [Rollback][google.spanner.v1.Spanner.Rollback] request to abort the
100// transaction.
101//
102// Semantics:
103//
104// Cloud Spanner can commit the transaction if all read locks it acquired
105// are still valid at commit time, and it is able to acquire write
106// locks for all writes. Cloud Spanner can abort the transaction for any
107// reason. If a commit attempt returns `ABORTED`, Cloud Spanner guarantees
108// that the transaction has not modified any user data in Cloud Spanner.
109//
110// Unless the transaction commits, Cloud Spanner makes no guarantees about
111// how long the transaction's locks were held for. It is an error to
112// use Cloud Spanner locks for any sort of mutual exclusion other than
113// between Cloud Spanner transactions themselves.
114//
115// Retrying aborted transactions:
116//
117// When a transaction aborts, the application can choose to retry the
118// whole transaction again. To maximize the chances of successfully
119// committing the retry, the client should execute the retry in the
120// same session as the original attempt. The original session's lock
121// priority increases with each consecutive abort, meaning that each
122// attempt has a slightly better chance of success than the previous.
123//
124// Under some circumstances (for example, many transactions attempting to
125// modify the same row(s)), a transaction can abort many times in a
126// short period before successfully committing. Thus, it is not a good
127// idea to cap the number of retries a transaction can attempt;
128// instead, it is better to limit the total amount of time spent
129// retrying.
130//
131// Idle transactions:
132//
133// A transaction is considered idle if it has no outstanding reads or
134// SQL queries and has not started a read or SQL query within the last 10
135// seconds. Idle transactions can be aborted by Cloud Spanner so that they
136// don't hold on to locks indefinitely. If an idle transaction is aborted, the
137// commit will fail with error `ABORTED`.
138//
139// If this behavior is undesirable, periodically executing a simple
140// SQL query in the transaction (for example, `SELECT 1`) prevents the
141// transaction from becoming idle.
142//
143// Snapshot read-only transactions:
144//
145// Snapshot read-only transactions provides a simpler method than
146// locking read-write transactions for doing several consistent
147// reads. However, this type of transaction does not support writes.
148//
149// Snapshot transactions do not take locks. Instead, they work by
150// choosing a Cloud Spanner timestamp, then executing all reads at that
151// timestamp. Since they do not acquire locks, they do not block
152// concurrent read-write transactions.
153//
154// Unlike locking read-write transactions, snapshot read-only
155// transactions never abort. They can fail if the chosen read
156// timestamp is garbage collected; however, the default garbage
157// collection policy is generous enough that most applications do not
158// need to worry about this in practice.
159//
160// Snapshot read-only transactions do not need to call
161// [Commit][google.spanner.v1.Spanner.Commit] or
162// [Rollback][google.spanner.v1.Spanner.Rollback] (and in fact are not
163// permitted to do so).
164//
165// To execute a snapshot transaction, the client specifies a timestamp
166// bound, which tells Cloud Spanner how to choose a read timestamp.
167//
168// The types of timestamp bound are:
169//
170//   - Strong (the default).
171//   - Bounded staleness.
172//   - Exact staleness.
173//
174// If the Cloud Spanner database to be read is geographically distributed,
175// stale read-only transactions can execute more quickly than strong
176// or read-write transactions, because they are able to execute far
177// from the leader replica.
178//
179// Each type of timestamp bound is discussed in detail below.
180//
181// Strong: Strong reads are guaranteed to see the effects of all transactions
182// that have committed before the start of the read. Furthermore, all
183// rows yielded by a single read are consistent with each other -- if
184// any part of the read observes a transaction, all parts of the read
185// see the transaction.
186//
187// Strong reads are not repeatable: two consecutive strong read-only
188// transactions might return inconsistent results if there are
189// concurrent writes. If consistency across reads is required, the
190// reads should be executed within a transaction or at an exact read
191// timestamp.
192//
193// Queries on change streams (see below for more details) must also specify
194// the strong read timestamp bound.
195//
196// See
197// [TransactionOptions.ReadOnly.strong][google.spanner.v1.TransactionOptions.ReadOnly.strong].
198//
199// Exact staleness:
200//
201// These timestamp bounds execute reads at a user-specified
202// timestamp. Reads at a timestamp are guaranteed to see a consistent
203// prefix of the global transaction history: they observe
204// modifications done by all transactions with a commit timestamp less than or
205// equal to the read timestamp, and observe none of the modifications done by
206// transactions with a larger commit timestamp. They will block until
207// all conflicting transactions that may be assigned commit timestamps
208// <= the read timestamp have finished.
209//
210// The timestamp can either be expressed as an absolute Cloud Spanner commit
211// timestamp or a staleness relative to the current time.
212//
213// These modes do not require a "negotiation phase" to pick a
214// timestamp. As a result, they execute slightly faster than the
215// equivalent boundedly stale concurrency modes. On the other hand,
216// boundedly stale reads usually return fresher results.
217//
218// See
219// [TransactionOptions.ReadOnly.read_timestamp][google.spanner.v1.TransactionOptions.ReadOnly.read_timestamp]
220// and
221// [TransactionOptions.ReadOnly.exact_staleness][google.spanner.v1.TransactionOptions.ReadOnly.exact_staleness].
222//
223// Bounded staleness:
224//
225// Bounded staleness modes allow Cloud Spanner to pick the read timestamp,
226// subject to a user-provided staleness bound. Cloud Spanner chooses the
227// newest timestamp within the staleness bound that allows execution
228// of the reads at the closest available replica without blocking.
229//
230// All rows yielded are consistent with each other -- if any part of
231// the read observes a transaction, all parts of the read see the
232// transaction. Boundedly stale reads are not repeatable: two stale
233// reads, even if they use the same staleness bound, can execute at
234// different timestamps and thus return inconsistent results.
235//
236// Boundedly stale reads execute in two phases: the first phase
237// negotiates a timestamp among all replicas needed to serve the
238// read. In the second phase, reads are executed at the negotiated
239// timestamp.
240//
241// As a result of the two phase execution, bounded staleness reads are
242// usually a little slower than comparable exact staleness
243// reads. However, they are typically able to return fresher
244// results, and are more likely to execute at the closest replica.
245//
246// Because the timestamp negotiation requires up-front knowledge of
247// which rows will be read, it can only be used with single-use
248// read-only transactions.
249//
250// See
251// [TransactionOptions.ReadOnly.max_staleness][google.spanner.v1.TransactionOptions.ReadOnly.max_staleness]
252// and
253// [TransactionOptions.ReadOnly.min_read_timestamp][google.spanner.v1.TransactionOptions.ReadOnly.min_read_timestamp].
254//
255// Old read timestamps and garbage collection:
256//
257// Cloud Spanner continuously garbage collects deleted and overwritten data
258// in the background to reclaim storage space. This process is known
259// as "version GC". By default, version GC reclaims versions after they
260// are one hour old. Because of this, Cloud Spanner cannot perform reads
261// at read timestamps more than one hour in the past. This
262// restriction also applies to in-progress reads and/or SQL queries whose
263// timestamp become too old while executing. Reads and SQL queries with
264// too-old read timestamps fail with the error `FAILED_PRECONDITION`.
265//
266// You can configure and extend the `VERSION_RETENTION_PERIOD` of a
267// database up to a period as long as one week, which allows Cloud Spanner
268// to perform reads up to one week in the past.
269//
270// Querying change Streams:
271//
272// A Change Stream is a schema object that can be configured to watch data
273// changes on the entire database, a set of tables, or a set of columns
274// in a database.
275//
276// When a change stream is created, Spanner automatically defines a
277// corresponding SQL Table-Valued Function (TVF) that can be used to query
278// the change records in the associated change stream using the
279// ExecuteStreamingSql API. The name of the TVF for a change stream is
280// generated from the name of the change stream: READ_<change_stream_name>.
281//
282// All queries on change stream TVFs must be executed using the
283// ExecuteStreamingSql API with a single-use read-only transaction with a
284// strong read-only timestamp_bound. The change stream TVF allows users to
285// specify the start_timestamp and end_timestamp for the time range of
286// interest. All change records within the retention period is accessible
287// using the strong read-only timestamp_bound. All other TransactionOptions
288// are invalid for change stream queries.
289//
290// In addition, if TransactionOptions.read_only.return_read_timestamp is set
291// to true, a special value of 2^63 - 2 will be returned in the
292// [Transaction][google.spanner.v1.Transaction] message that describes the
293// transaction, instead of a valid read timestamp. This special value should be
294// discarded and not used for any subsequent queries.
295//
296// Please see https://cloud.google.com/spanner/docs/change-streams
297// for more details on how to query the change stream TVFs.
298//
299// Partitioned DML transactions:
300//
301// Partitioned DML transactions are used to execute DML statements with a
302// different execution strategy that provides different, and often better,
303// scalability properties for large, table-wide operations than DML in a
304// ReadWrite transaction. Smaller scoped statements, such as an OLTP workload,
305// should prefer using ReadWrite transactions.
306//
307// Partitioned DML partitions the keyspace and runs the DML statement on each
308// partition in separate, internal transactions. These transactions commit
309// automatically when complete, and run independently from one another.
310//
311// To reduce lock contention, this execution strategy only acquires read locks
312// on rows that match the WHERE clause of the statement. Additionally, the
313// smaller per-partition transactions hold locks for less time.
314//
315// That said, Partitioned DML is not a drop-in replacement for standard DML used
316// in ReadWrite transactions.
317//
318//  - The DML statement must be fully-partitionable. Specifically, the statement
319//    must be expressible as the union of many statements which each access only
320//    a single row of the table.
321//
322//  - The statement is not applied atomically to all rows of the table. Rather,
323//    the statement is applied atomically to partitions of the table, in
324//    independent transactions. Secondary index rows are updated atomically
325//    with the base table rows.
326//
327//  - Partitioned DML does not guarantee exactly-once execution semantics
328//    against a partition. The statement will be applied at least once to each
329//    partition. It is strongly recommended that the DML statement should be
330//    idempotent to avoid unexpected results. For instance, it is potentially
331//    dangerous to run a statement such as
332//    `UPDATE table SET column = column + 1` as it could be run multiple times
333//    against some rows.
334//
335//  - The partitions are committed automatically - there is no support for
336//    Commit or Rollback. If the call returns an error, or if the client issuing
337//    the ExecuteSql call dies, it is possible that some rows had the statement
338//    executed on them successfully. It is also possible that statement was
339//    never executed against other rows.
340//
341//  - Partitioned DML transactions may only contain the execution of a single
342//    DML statement via ExecuteSql or ExecuteStreamingSql.
343//
344//  - If any error is encountered during the execution of the partitioned DML
345//    operation (for instance, a UNIQUE INDEX violation, division by zero, or a
346//    value that cannot be stored due to schema constraints), then the
347//    operation is stopped at that point and an error is returned. It is
348//    possible that at this point, some partitions have been committed (or even
349//    committed multiple times), and other partitions have not been run at all.
350//
351// Given the above, Partitioned DML is good fit for large, database-wide,
352// operations that are idempotent, such as deleting old rows from a very large
353// table.
354message TransactionOptions {
355  // Message type to initiate a read-write transaction. Currently this
356  // transaction type has no options.
357  message ReadWrite {
358    // `ReadLockMode` is used to set the read lock mode for read-write
359    // transactions.
360    enum ReadLockMode {
361      // Default value.
362      //
363      // If the value is not specified, the pessimistic read lock is used.
364      READ_LOCK_MODE_UNSPECIFIED = 0;
365
366      // Pessimistic lock mode.
367      //
368      // Read locks are acquired immediately on read.
369      PESSIMISTIC = 1;
370
371      // Optimistic lock mode.
372      //
373      // Locks for reads within the transaction are not acquired on read.
374      // Instead the locks are acquired on a commit to validate that
375      // read/queried data has not changed since the transaction started.
376      OPTIMISTIC = 2;
377    }
378
379    // Read lock mode for the transaction.
380    ReadLockMode read_lock_mode = 1;
381  }
382
383  // Message type to initiate a Partitioned DML transaction.
384  message PartitionedDml {}
385
386  // Message type to initiate a read-only transaction.
387  message ReadOnly {
388    // How to choose the timestamp for the read-only transaction.
389    oneof timestamp_bound {
390      // Read at a timestamp where all previously committed transactions
391      // are visible.
392      bool strong = 1;
393
394      // Executes all reads at a timestamp >= `min_read_timestamp`.
395      //
396      // This is useful for requesting fresher data than some previous
397      // read, or data that is fresh enough to observe the effects of some
398      // previously committed transaction whose timestamp is known.
399      //
400      // Note that this option can only be used in single-use transactions.
401      //
402      // A timestamp in RFC3339 UTC \"Zulu\" format, accurate to nanoseconds.
403      // Example: `"2014-10-02T15:01:23.045123456Z"`.
404      google.protobuf.Timestamp min_read_timestamp = 2;
405
406      // Read data at a timestamp >= `NOW - max_staleness`
407      // seconds. Guarantees that all writes that have committed more
408      // than the specified number of seconds ago are visible. Because
409      // Cloud Spanner chooses the exact timestamp, this mode works even if
410      // the client's local clock is substantially skewed from Cloud Spanner
411      // commit timestamps.
412      //
413      // Useful for reading the freshest data available at a nearby
414      // replica, while bounding the possible staleness if the local
415      // replica has fallen behind.
416      //
417      // Note that this option can only be used in single-use
418      // transactions.
419      google.protobuf.Duration max_staleness = 3;
420
421      // Executes all reads at the given timestamp. Unlike other modes,
422      // reads at a specific timestamp are repeatable; the same read at
423      // the same timestamp always returns the same data. If the
424      // timestamp is in the future, the read will block until the
425      // specified timestamp, modulo the read's deadline.
426      //
427      // Useful for large scale consistent reads such as mapreduces, or
428      // for coordinating many reads against a consistent snapshot of the
429      // data.
430      //
431      // A timestamp in RFC3339 UTC \"Zulu\" format, accurate to nanoseconds.
432      // Example: `"2014-10-02T15:01:23.045123456Z"`.
433      google.protobuf.Timestamp read_timestamp = 4;
434
435      // Executes all reads at a timestamp that is `exact_staleness`
436      // old. The timestamp is chosen soon after the read is started.
437      //
438      // Guarantees that all writes that have committed more than the
439      // specified number of seconds ago are visible. Because Cloud Spanner
440      // chooses the exact timestamp, this mode works even if the client's
441      // local clock is substantially skewed from Cloud Spanner commit
442      // timestamps.
443      //
444      // Useful for reading at nearby replicas without the distributed
445      // timestamp negotiation overhead of `max_staleness`.
446      google.protobuf.Duration exact_staleness = 5;
447    }
448
449    // If true, the Cloud Spanner-selected read timestamp is included in
450    // the [Transaction][google.spanner.v1.Transaction] message that describes
451    // the transaction.
452    bool return_read_timestamp = 6;
453  }
454
455  // Required. The type of transaction.
456  oneof mode {
457    // Transaction may write.
458    //
459    // Authorization to begin a read-write transaction requires
460    // `spanner.databases.beginOrRollbackReadWriteTransaction` permission
461    // on the `session` resource.
462    ReadWrite read_write = 1;
463
464    // Partitioned DML transaction.
465    //
466    // Authorization to begin a Partitioned DML transaction requires
467    // `spanner.databases.beginPartitionedDmlTransaction` permission
468    // on the `session` resource.
469    PartitionedDml partitioned_dml = 3;
470
471    // Transaction will not write.
472    //
473    // Authorization to begin a read-only transaction requires
474    // `spanner.databases.beginReadOnlyTransaction` permission
475    // on the `session` resource.
476    ReadOnly read_only = 2;
477  }
478
479  // When `exclude_txn_from_change_streams` is set to `true`:
480  //  * Mutations from this transaction will not be recorded in change streams
481  //  with DDL option `allow_txn_exclusion=true` that are tracking columns
482  //  modified by these transactions.
483  //  * Mutations from this transaction will be recorded in change streams with
484  //  DDL option `allow_txn_exclusion=false or not set` that are tracking
485  //  columns modified by these transactions.
486  //
487  // When `exclude_txn_from_change_streams` is set to `false` or not set,
488  // mutations from this transaction will be recorded in all change streams that
489  // are tracking columns modified by these transactions.
490  // `exclude_txn_from_change_streams` may only be specified for read-write or
491  // partitioned-dml transactions, otherwise the API will return an
492  // `INVALID_ARGUMENT` error.
493  bool exclude_txn_from_change_streams = 5;
494}
495
496// A transaction.
497message Transaction {
498  // `id` may be used to identify the transaction in subsequent
499  // [Read][google.spanner.v1.Spanner.Read],
500  // [ExecuteSql][google.spanner.v1.Spanner.ExecuteSql],
501  // [Commit][google.spanner.v1.Spanner.Commit], or
502  // [Rollback][google.spanner.v1.Spanner.Rollback] calls.
503  //
504  // Single-use read-only transactions do not have IDs, because
505  // single-use transactions do not support multiple requests.
506  bytes id = 1;
507
508  // For snapshot read-only transactions, the read timestamp chosen
509  // for the transaction. Not returned by default: see
510  // [TransactionOptions.ReadOnly.return_read_timestamp][google.spanner.v1.TransactionOptions.ReadOnly.return_read_timestamp].
511  //
512  // A timestamp in RFC3339 UTC \"Zulu\" format, accurate to nanoseconds.
513  // Example: `"2014-10-02T15:01:23.045123456Z"`.
514  google.protobuf.Timestamp read_timestamp = 2;
515}
516
517// This message is used to select the transaction in which a
518// [Read][google.spanner.v1.Spanner.Read] or
519// [ExecuteSql][google.spanner.v1.Spanner.ExecuteSql] call runs.
520//
521// See [TransactionOptions][google.spanner.v1.TransactionOptions] for more
522// information about transactions.
523message TransactionSelector {
524  // If no fields are set, the default is a single use transaction
525  // with strong concurrency.
526  oneof selector {
527    // Execute the read or SQL query in a temporary transaction.
528    // This is the most efficient way to execute a transaction that
529    // consists of a single SQL query.
530    TransactionOptions single_use = 1;
531
532    // Execute the read or SQL query in a previously-started transaction.
533    bytes id = 2;
534
535    // Begin a new transaction and execute this read or SQL query in
536    // it. The transaction ID of the new transaction is returned in
537    // [ResultSetMetadata.transaction][google.spanner.v1.ResultSetMetadata.transaction],
538    // which is a [Transaction][google.spanner.v1.Transaction].
539    TransactionOptions begin = 3;
540  }
541}
542