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