Skip to content

Commit ee2f09c

Browse files
committed
feat(spanner): samples to set transaction options
Adds samples that show how to set the isolation level and read lock mode at the Spanner client level and at a transaction level. If it's set at the client level, all RW transactions will set this value. The transaction-level setting allows users to override the client-level setting or to set the values for specific transactions.
1 parent 69ce74b commit ee2f09c

4 files changed

Lines changed: 174 additions & 0 deletions

File tree

spanner/spanner_isolation_level.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2026 Google, Inc
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+
15+
# [START spanner_isolation_level]
16+
require "google/cloud/spanner"
17+
18+
def spanner_isolation_level project_id:, instance_id:, database_id:
19+
# Instantiates a client with isolation_level: :SERIALIZABLE
20+
spanner = Google::Cloud::Spanner.new project: project_id
21+
client = spanner.client instance_id, database_id, isolation_level: :SERIALIZABLE
22+
23+
# Overrides isolation_level to :REPEATABLE_READ at transaction level
24+
client.transaction isolation_level: :REPEATABLE_READ do |tx|
25+
results = tx.execute_query "SELECT AlbumTitle FROM Albums WHERE SingerId = 1 AND AlbumId = 1"
26+
27+
results.rows.each do |row|
28+
puts "AlbumTitle: #{row[:AlbumTitle]}"
29+
end
30+
31+
row_count = tx.execute_update "UPDATE Albums SET AlbumTitle = 'A New Title' WHERE SingerId = 1 AND AlbumId = 1"
32+
33+
puts "#{row_count} records updated."
34+
end
35+
end
36+
# [END spanner_isolation_level]

spanner/spanner_read_lock_mode.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2026 Google, Inc
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+
15+
# [START spanner_read_lock_mode]
16+
require "google/cloud/spanner"
17+
18+
def spanner_read_lock_mode project_id:, instance_id:, database_id:
19+
# Instantiates a client with read_lock_mode: :OPTIMISTIC
20+
spanner = Google::Cloud::Spanner.new project: project_id
21+
client = spanner.client instance_id, database_id, read_lock_mode: :OPTIMISTIC
22+
23+
# Overrides read_lock_mode to :PESSIMISTIC at transaction level
24+
client.transaction read_lock_mode: :PESSIMISTIC do |tx|
25+
results = tx.execute_query "SELECT AlbumTitle FROM Albums WHERE SingerId = 2 AND AlbumId = 1"
26+
27+
results.rows.each do |row|
28+
puts "AlbumTitle: #{row[:AlbumTitle]}"
29+
end
30+
31+
row_count = tx.execute_update "UPDATE Albums SET AlbumTitle = 'A New Title' WHERE SingerId = 2 AND AlbumId = 1"
32+
33+
puts "#{row_count} records updated."
34+
end
35+
end
36+
# [END spanner_read_lock_mode]
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright 2026 Google, Inc
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+
15+
require_relative "../spanner_isolation_level"
16+
require "rspec"
17+
require "google/cloud/spanner"
18+
19+
describe "Spanner Isolation Level Options" do
20+
it "runs isolation level snippet successfully" do
21+
if ENV["GOOGLE_CLOUD_SPANNER_TEST_INSTANCE"].nil? || ENV["GOOGLE_CLOUD_SPANNER_PROJECT"].nil?
22+
skip "GOOGLE_CLOUD_SPANNER_TEST_INSTANCE and/or GOOGLE_CLOUD_SPANNER_PROJECT not defined"
23+
end
24+
25+
@project_id = ENV["GOOGLE_CLOUD_SPANNER_PROJECT"]
26+
@instance_id = ENV["GOOGLE_CLOUD_SPANNER_TEST_INSTANCE"]
27+
@seed = SecureRandom.hex 8
28+
@database_id = "test_db_#{@seed}"
29+
@spanner = Google::Cloud::Spanner.new project: @project_id
30+
@instance = @spanner.instance @instance_id
31+
32+
unless @instance.database @database_id
33+
real_stdout = $stdout
34+
$stdout = StringIO.new
35+
create_database project_id: @project_id,
36+
instance_id: @instance_id,
37+
database_id: @database_id
38+
$stdout = real_stdout
39+
end
40+
41+
client = @spanner.client @instance_id, @database_id
42+
client.insert "Singers", [{ SingerId: 1, FirstName: "Test" }]
43+
client.insert "Albums", [{ SingerId: 1, AlbumId: 1, AlbumTitle: "Old Title" }]
44+
45+
expect {
46+
spanner_isolation_level project_id: @project_id, instance_id: @instance_id, database_id: @database_id
47+
}.to output(/AlbumTitle: Old Title\n1 records updated./).to_stdout
48+
49+
@instance.database(@database_id).drop
50+
end
51+
end
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright 2026 Google, Inc
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+
15+
require_relative "../spanner_read_lock_mode"
16+
require "rspec"
17+
require "google/cloud/spanner"
18+
19+
describe "Spanner Read Lock Mode Options" do
20+
it "runs read lock mode snippet successfully" do
21+
if ENV["GOOGLE_CLOUD_SPANNER_TEST_INSTANCE"].nil? || ENV["GOOGLE_CLOUD_SPANNER_PROJECT"].nil?
22+
skip "GOOGLE_CLOUD_SPANNER_TEST_INSTANCE and/or GOOGLE_CLOUD_SPANNER_PROJECT not defined"
23+
end
24+
25+
@project_id = ENV["GOOGLE_CLOUD_SPANNER_PROJECT"]
26+
@instance_id = ENV["GOOGLE_CLOUD_SPANNER_TEST_INSTANCE"]
27+
@seed = SecureRandom.hex 8
28+
@database_id = "test_db_#{@seed}"
29+
@spanner = Google::Cloud::Spanner.new project: @project_id
30+
@instance = @spanner.instance @instance_id
31+
32+
unless @instance.database @database_id
33+
real_stdout = $stdout
34+
$stdout = StringIO.new
35+
create_database project_id: @project_id,
36+
instance_id: @instance_id,
37+
database_id: @database_id
38+
$stdout = real_stdout
39+
end
40+
41+
client = @spanner.client @instance_id, @database_id
42+
client.insert "Singers", [{ SingerId: 2, FirstName: "Test" }]
43+
client.insert "Albums", [{ SingerId: 2, AlbumId: 1, AlbumTitle: "Old Title" }]
44+
45+
expect {
46+
spanner_read_lock_mode project_id: @project_id, instance_id: @instance_id, database_id: @database_id
47+
}.to output(/AlbumTitle: Old Title\n1 records updated./).to_stdout
48+
49+
@instance.database(@database_id).drop
50+
end
51+
end

0 commit comments

Comments
 (0)