ASnapshotrepresents a read-only
transaction: when multiple read operations are performed via a Snapshot,
the results are consistent as of a particular point in time.
Beginning a Snapshot
To begin using a snapshot using the default “bound” (which is “strong”),
meaning all reads are performed at a timestamp where all previously-committed
transactions are visible:
with database.snapshot() as snapshot:
...
You can also specify a weaker bound, which can either be to perform all
reads as of a given timestamp:
import datetime
TIMESTAMP = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
with database.snapshot(read_timestamp=TIMESTAMP) as snapshot:
...
or as of a given duration in the past:
import datetime
DURATION = datetime.timedelta(seconds=5)
with database.snapshot(exact_staleness=DURATION) as snapshot:
...
Single Use and Multiple Use Snapshots
In the context of read only transactions,readandexecute_sqlmethods can be used multiple times if you specifymulti_use=Truein the constructor of the snapshot. However,multi_use=Trueis
incompatible with eithermax_stalenessand/ormin_read_timestamp.
Otherwisemulti_usedefaults toFalseand the snapshot cannot be
reused.
with database.snapshot(multi_use=True) as snapshot:
...
begin()can only be used on a
snapshot withmulti_use=True. In which case it is also necessary
to call if you need to have multiple pending operations.
Read Table Data
To read data for selected rows from a table in the database, callread()which will return
all rows specified inkeyset, or fail if the result set is too large,
with database.snapshot() as snapshot:
result = snapshot.read(
table='table-name', columns=['first_name', 'last_name', 'age'],
keyset=spanner.KeySet([['phred@example.com'], ['bharney@example.com']]))
for row in result:
print(row)
NOTE: Perform all iterations within the context of thewith database.snapshot()block.
Execute a SQL Select Statement
To read data from tables in the database using a query, callexecute_sql()which will return all rows matching the query, or fail if the
result set is too large,
with database.snapshot() as snapshot:
QUERY = (
'SELECT e.first_name, e.last_name, p.telephone '
'FROM employees as e, phones as p '
'WHERE p.employee_id == e.employee_id')
result = snapshot.execute_sql(QUERY)
for row in result:
print(row)
NOTE: Perform all iteration within the context of thewith database.snapshot()block.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-04 UTC."],[],[],null,["Version latestkeyboard_arrow_down\n\n- [3.57.0 (latest)](/python/docs/reference/spanner/latest/snapshot-usage)\n- [3.56.0](/python/docs/reference/spanner/3.56.0/snapshot-usage)\n- [3.55.0](/python/docs/reference/spanner/3.55.0/snapshot-usage)\n- [3.54.0](/python/docs/reference/spanner/3.54.0/snapshot-usage)\n- [3.53.0](/python/docs/reference/spanner/3.53.0/snapshot-usage)\n- [3.52.0](/python/docs/reference/spanner/3.52.0/snapshot-usage)\n- [3.51.0](/python/docs/reference/spanner/3.51.0/snapshot-usage)\n- [3.50.1](/python/docs/reference/spanner/3.50.1/snapshot-usage)\n- [3.46.0](/python/docs/reference/spanner/3.46.0/snapshot-usage)\n- [3.45.0](/python/docs/reference/spanner/3.45.0/snapshot-usage)\n- [3.44.0](/python/docs/reference/spanner/3.44.0/snapshot-usage)\n- [3.43.0](/python/docs/reference/spanner/3.43.0/snapshot-usage)\n- [3.42.0](/python/docs/reference/spanner/3.42.0/snapshot-usage)\n- [3.41.0](/python/docs/reference/spanner/3.41.0/snapshot-usage)\n- [3.40.1](/python/docs/reference/spanner/3.40.1/snapshot-usage)\n- [3.39.0](/python/docs/reference/spanner/3.39.0/snapshot-usage)\n- [3.38.0](/python/docs/reference/spanner/3.38.0/snapshot-usage)\n- [3.37.0](/python/docs/reference/spanner/3.37.0/snapshot-usage)\n- [3.36.0](/python/docs/reference/spanner/3.36.0/snapshot-usage)\n- [3.35.1](/python/docs/reference/spanner/3.35.1/snapshot-usage)\n- [3.34.0](/python/docs/reference/spanner/3.34.0/snapshot-usage)\n- [3.33.0](/python/docs/reference/spanner/3.33.0/snapshot-usage)\n- [3.32.0](/python/docs/reference/spanner/3.32.0/snapshot-usage)\n- [3.31.0](/python/docs/reference/spanner/3.31.0/snapshot-usage)\n- [3.30.0](/python/docs/reference/spanner/3.30.0/snapshot-usage)\n- [3.29.0](/python/docs/reference/spanner/3.29.0/snapshot-usage)\n- [3.28.0](/python/docs/reference/spanner/3.28.0/snapshot-usage)\n- [3.27.1](/python/docs/reference/spanner/3.27.1/snapshot-usage)\n- [3.26.0](/python/docs/reference/spanner/3.26.0/snapshot-usage)\n- [3.25.0](/python/docs/reference/spanner/3.25.0/snapshot-usage)\n- [3.24.0](/python/docs/reference/spanner/3.24.0/snapshot-usage)\n- [3.23.0](/python/docs/reference/spanner/3.23.0/snapshot-usage)\n- [3.22.2](/python/docs/reference/spanner/3.22.2/snapshot-usage)\n- [3.21.0](/python/docs/reference/spanner/3.21.0/snapshot-usage)\n- [3.20.0](/python/docs/reference/spanner/3.20.0/snapshot-usage)\n- [3.19.0](/python/docs/reference/spanner/3.19.0/snapshot-usage)\n- [3.18.0](/python/docs/reference/spanner/3.18.0/snapshot-usage)\n- [3.17.0](/python/docs/reference/spanner/3.17.0/snapshot-usage)\n- [3.16.0](/python/docs/reference/spanner/3.16.0/snapshot-usage)\n- [3.15.1](/python/docs/reference/spanner/3.15.1/snapshot-usage)\n- [3.14.1](/python/docs/reference/spanner/3.14.1/snapshot-usage)\n- [3.13.0](/python/docs/reference/spanner/3.13.0/snapshot-usage)\n- [3.12.1](/python/docs/reference/spanner/3.12.1/snapshot-usage)\n- [3.11.1](/python/docs/reference/spanner/3.11.1/snapshot-usage)\n- [3.10.0](/python/docs/reference/spanner/3.10.0/snapshot-usage)\n- [3.9.0](/python/docs/reference/spanner/3.9.0/snapshot-usage)\n- [3.8.0](/python/docs/reference/spanner/3.8.0/snapshot-usage)\n- [3.7.0](/python/docs/reference/spanner/3.7.0/snapshot-usage)\n- [3.6.0](/python/docs/reference/spanner/3.6.0/snapshot-usage)\n- [3.5.0](/python/docs/reference/spanner/3.5.0/snapshot-usage)\n- [3.4.0](/python/docs/reference/spanner/3.4.0/snapshot-usage)\n- [3.3.0](/python/docs/reference/spanner/3.3.0/snapshot-usage)\n- [3.2.0](/python/docs/reference/spanner/3.2.0/snapshot-usage)\n- [3.1.0](/python/docs/reference/spanner/3.1.0/snapshot-usage)\n- [3.0.0](/python/docs/reference/spanner/3.0.0/snapshot-usage)\n- [2.1.1](/python/docs/reference/spanner/2.1.1/snapshot-usage)\n- [2.0.0](/python/docs/reference/spanner/2.0.0/snapshot-usage)\n- [1.19.3](/python/docs/reference/spanner/1.19.3/snapshot-usage)\n- [1.18.0](/python/docs/reference/spanner/1.18.0/snapshot-usage)\n- [1.17.1](/python/docs/reference/spanner/1.17.1/snapshot-usage)\n- [1.16.0](/python/docs/reference/spanner/1.16.0/snapshot-usage)\n- [1.15.1](/python/docs/reference/spanner/1.15.1/snapshot-usage)\n- [1.14.0](/python/docs/reference/spanner/1.14.0/snapshot-usage)\n- [1.13.0](/python/docs/reference/spanner/1.13.0/snapshot-usage)\n- [1.12.0](/python/docs/reference/spanner/1.12.0/snapshot-usage)\n- [1.11.0](/python/docs/reference/spanner/1.11.0/snapshot-usage)\n- [1.10.0](/python/docs/reference/spanner/1.10.0/snapshot-usage) \n\nRead-only Transactions via Snapshots\n====================================\n\nA [`Snapshot`](/python/docs/reference/spanner/latest/spanner_v1/snapshot#google.cloud.spanner_v1.snapshot.Snapshot) represents a read-only\ntransaction: when multiple read operations are performed via a Snapshot,\nthe results are consistent as of a particular point in time.\n\nBeginning a Snapshot\n--------------------\n\nTo begin using a snapshot using the default \"bound\" (which is \"strong\"),\nmeaning all reads are performed at a timestamp where all previously-committed\ntransactions are visible: \n\n with database.snapshot() as snapshot:\n ...\n\nYou can also specify a weaker bound, which can either be to perform all\nreads as of a given timestamp: \n\n import datetime\n TIMESTAMP = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)\n\n with database.snapshot(read_timestamp=TIMESTAMP) as snapshot:\n ...\n\nor as of a given duration in the past: \n\n import datetime\n DURATION = datetime.timedelta(seconds=5)\n\n with database.snapshot(exact_staleness=DURATION) as snapshot:\n ...\n\nSingle Use and Multiple Use Snapshots\n-------------------------------------\n\nIn the context of read only transactions, `read` and `execute_sql`\nmethods can be used multiple times if you specify `multi_use=True`\nin the constructor of the snapshot. However, `multi_use=True` is\nincompatible with either `max_staleness` and/or `min_read_timestamp`.\n\nOtherwise `multi_use` defaults to `False` and the snapshot cannot be\nreused. \n\n with database.snapshot(multi_use=True) as snapshot:\n ...\n\n[`begin()`](/python/docs/reference/spanner/latest/spanner_v1/snapshot#google.cloud.spanner_v1.snapshot.Snapshot.begin) can only be used on a\nsnapshot with `multi_use=True`. In which case it is also necessary\nto call if you need to have multiple pending operations.\n\nRead Table Data\n---------------\n\nTo read data for selected rows from a table in the database, call\n[`read()`](/python/docs/reference/spanner/latest/spanner_v1/snapshot#google.cloud.spanner_v1.snapshot.Snapshot.read) which will return\nall rows specified in `keyset`, or fail if the result set is too large, \n\n with database.snapshot() as snapshot:\n result = snapshot.read(\n table='table-name', columns=['first_name', 'last_name', 'age'],\n keyset=spanner.KeySet([['phred@example.com'], ['bharney@example.com']]))\n\n for row in result:\n print(row)\n\n**NOTE** : Perform all iterations within the context of the `with database.snapshot()`\nblock.\n\nExecute a SQL Select Statement\n------------------------------\n\nTo read data from tables in the database using a query, call\n[`execute_sql()`](/python/docs/reference/spanner/latest/spanner_v1/snapshot#google.cloud.spanner_v1.snapshot.Snapshot.execute_sql)\nwhich will return all rows matching the query, or fail if the\nresult set is too large, \n\n with database.snapshot() as snapshot:\n QUERY = (\n 'SELECT e.first_name, e.last_name, p.telephone '\n 'FROM employees as e, phones as p '\n 'WHERE p.employee_id == e.employee_id')\n result = snapshot.execute_sql(QUERY)\n\n for row in result:\n print(row)\n\n**NOTE** : Perform all iteration within the context of the `with database.snapshot()`\nblock.\n\nNext Step\n---------\n\nNext, learn about [Read-write Transactions](/python/docs/reference/spanner/latest/transaction-usage)."]]