From 7ddc6dbbb4760dae50e9fc7d3d6aab1549c2ecb2 Mon Sep 17 00:00:00 2001 From: skuruppu Date: Fri, 9 Jan 2026 00:27:33 +0000 Subject: [PATCH] docs(spanner): snippet for setting read lock mode Snippet shows how to set the read lock mode at the client-level and how to override the option at the transaction-level. --- samples/samples/snippets.py | 60 ++++++++++++++++++++++++++++++++ samples/samples/snippets_test.py | 9 ++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/samples/samples/snippets.py b/samples/samples/snippets.py index 96d8fd3f89..885179d298 100644 --- a/samples/samples/snippets.py +++ b/samples/samples/snippets.py @@ -3232,6 +3232,61 @@ def update_albums_with_isolation(transaction): # [END spanner_isolation_level] +def read_lock_mode_options( + instance_id, + database_id, +): + from google.cloud.spanner_v1 import TransactionOptions, DefaultTransactionOptions + + """ + Shows how to run a Read Write transaction with read lock mode options. + """ + # [START spanner_read_lock_mode] + # instance_id = "your-spanner-instance" + # database_id = "your-spanner-db-id" + + # The read lock mode specified at the client-level will be applied to all + # RW transactions. + read_lock_mode_options_for_client = TransactionOptions.ReadWrite.ReadLockMode.OPTIMISTIC + + # Create a client that uses Serializable isolation (default) with + # optimistic locking for read-write transactions. + spanner_client = spanner.Client( + default_transaction_options=DefaultTransactionOptions( + read_lock_mode=read_lock_mode_options_for_client + ) + ) + instance = spanner_client.instance(instance_id) + database = instance.database(database_id) + + # The read lock mode specified at the request level takes precedence over + # the read lock mode configured at the client level. + read_lock_mode_options_for_transaction = ( + TransactionOptions.ReadWrite.ReadLockMode.PESSIMISTIC + ) + + def update_albums_with_read_lock_mode(transaction): + # Read an AlbumTitle. + results = transaction.execute_sql( + "SELECT AlbumTitle from Albums WHERE SingerId = 2 and AlbumId = 1" + ) + for result in results: + print("Current Album Title: {}".format(*result)) + + # Update the AlbumTitle. + row_ct = transaction.execute_update( + "UPDATE Albums SET AlbumTitle = 'A New Title' WHERE SingerId = 2 and AlbumId = 1" + ) + + print("{} record(s) updated.".format(row_ct)) + + database.run_in_transaction( + update_albums_with_read_lock_mode, + read_lock_mode=read_lock_mode_options_for_transaction + ) + # [END spanner_read_lock_mode] + + def set_custom_timeout_and_retry(instance_id, database_id): """Executes a snapshot read with custom timeout and retry.""" # [START spanner_set_custom_timeout_and_retry] @@ -3856,6 +3911,9 @@ def add_split_points(instance_id, database_id): subparsers.add_parser( "isolation_level_options", help=isolation_level_options.__doc__ ) + subparsers.add_parser( + "read_lock_mode_options", help=read_lock_mode_options.__doc__ + ) subparsers.add_parser( "set_custom_timeout_and_retry", help=set_custom_timeout_and_retry.__doc__ ) @@ -4018,6 +4076,8 @@ def add_split_points(instance_id, database_id): directed_read_options(args.instance_id, args.database_id) elif args.command == "isolation_level_options": isolation_level_options(args.instance_id, args.database_id) + elif args.command == "read_lock_mode_options": + read_lock_mode_options(args.instance_id, args.database_id) elif args.command == "set_custom_timeout_and_retry": set_custom_timeout_and_retry(args.instance_id, args.database_id) elif args.command == "create_instance_with_autoscaling_config": diff --git a/samples/samples/snippets_test.py b/samples/samples/snippets_test.py index 03c9f2682c..3888bf0120 100644 --- a/samples/samples/snippets_test.py +++ b/samples/samples/snippets_test.py @@ -993,12 +993,19 @@ def test_set_custom_timeout_and_retry(capsys, instance_id, sample_database): @pytest.mark.dependency(depends=["insert_data"]) -def test_isolated_level_options(capsys, instance_id, sample_database): +def test_isolation_level_options(capsys, instance_id, sample_database): snippets.isolation_level_options(instance_id, sample_database.database_id) out, _ = capsys.readouterr() assert "1 record(s) updated." in out +@pytest.mark.dependency(depends=["insert_data"]) +def test_read_lock_mode_options(capsys, instance_id, sample_database): + snippets.read_lock_mode_options(instance_id, sample_database.database_id) + out, _ = capsys.readouterr() + assert "1 record(s) updated." in out + + @pytest.mark.dependency( name="add_proto_types_column", )