Module: Google::Cloud::Spanner
- Defined in:
- lib/google/cloud/spanner.rb,
lib/google/cloud/spanner/data.rb,
lib/google/cloud/spanner/pool.rb,
lib/google/cloud/spanner/range.rb,
lib/google/cloud/spanner/client.rb,
lib/google/cloud/spanner/commit.rb,
lib/google/cloud/spanner/errors.rb,
lib/google/cloud/spanner/fields.rb,
lib/google/cloud/spanner/policy.rb,
lib/google/cloud/spanner/status.rb,
lib/google/cloud/spanner/convert.rb,
lib/google/cloud/spanner/project.rb,
lib/google/cloud/spanner/results.rb,
lib/google/cloud/spanner/service.rb,
lib/google/cloud/spanner/session.rb,
lib/google/cloud/spanner/version.rb,
lib/google/cloud/spanner/database.rb,
lib/google/cloud/spanner/instance.rb,
lib/google/cloud/spanner/snapshot.rb,
lib/google/cloud/spanner/credentials.rb,
lib/google/cloud/spanner/transaction.rb,
lib/google/cloud/spanner/database/job.rb,
lib/google/cloud/spanner/instance/job.rb,
lib/google/cloud/spanner/database/list.rb,
lib/google/cloud/spanner/instance/list.rb,
lib/google/cloud/spanner/instance/config.rb,
lib/google/cloud/spanner/v1/spanner_client.rb,
lib/google/cloud/spanner/instance/config/list.rb,
lib/google/cloud/spanner/admin/database/v1/database_admin_client.rb,
lib/google/cloud/spanner/admin/instance/v1/instance_admin_client.rb
Overview
Cloud Spanner
Cloud Spanner is a fully managed, mission-critical, relational database service that offers transactional consistency at global scale, schemas, SQL (ANSI 2011 with extensions), and automatic, synchronous replication for high availability.
For more information about Cloud Spanner, read the Cloud Spanner Documentation.
The goal of google-cloud is to provide an API that is comfortable to Rubyists. Authentication is handled by #spanner. You can provide the project and credential information to connect to the Cloud Spanner service, or if you are running on Google Compute Engine this configuration is taken care of for you. You can read more about the options for connecting in the Authentication Guide.
Creating instances
When you first use Cloud Spanner, you must create an instance, which is an allocation of resources that are used by Cloud Spanner databases. When you create an instance, you choose where your data is stored and how many nodes are used for your data. (For more information, see Instance Configuration).
Use Project#create_instance to create an instance:
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
job = spanner.create_instance "my-instance",
name: "My Instance",
config: "regional-us-central1",
nodes: 5,
labels: { production: :env }
job.done? #=> false
job.reload! # API call
job.done? #=> true
instance = job.instance
Creating databases
Now that you have created an instance, you can create a database. Cloud Spanner databases hold the tables and indexes that allow you to read and write data. You may create multiple databases in an instance.
Use Project#create_database (or Instance#create_database) to create a database:
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
job = spanner.create_database "my-instance", "my-database"
job.done? #=> false
job.reload! # API call
job.done? #=> true
database = job.database
Updating database schemas
Cloud Spanner supports schema updates to a database while the database continues to serve traffic. Schema updates do not require taking the database offline and they do not lock entire tables or columns; you can continue writing data to the database during the schema update.
Use Database#update to execute one or more statements in Cloud Spanner's Data Definition Language (DDL):
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
database = spanner.database "my-instance", "my-database"
add_users_table_sql = %q(
CREATE TABLE users (
id INT64 NOT NULL,
username STRING(25) NOT NULL,
name STRING(45) NOT NULL,
email STRING(128),
) PRIMARY KEY(id)
)
database.update statements: [add_users_table_sql]
Creating clients
In order to read and/or write data, you must create a database client. You can think of a client as a database connection: All of your interactions with Cloud Spanner data must go through a client. Typically you create a client when your application starts up, then you re-use that client to read, write, and execute transactions.
Use Project#client to create a client:
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"
results = db.execute "SELECT 1"
results.rows.each do |row|
puts row
end
Writing data
You write data using your client object. The client object supports various mutation operations, as well as combinations of inserts, updates, deletes, etc., that can be applied atomically to different rows and/or tables in a database.
Use Client#commit to execute various mutations atomically at a single logical point in time. All changes are accumulated in memory until the block completes. Unlike Client#transaction, which can also perform reads, this operation accepts only mutations and makes a single API request.
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"
db.commit do |c|
c.update "users", [{ id: 1, username: "charlie94", name: "Charlie" }]
c.insert "users", [{ id: 2, username: "harvey00", name: "Harvey" }]
end
Querying data using SQL
Cloud Spanner supports a native SQL interface for reading data that is available through Client#execute:
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"
results = db.execute "SELECT * FROM users"
results.rows.each do |row|
puts "User #{row[:id]} is #{row[:name]}"
end
Reading data using the read method
In addition to Cloud Spanner's SQL interface, Cloud Spanner also supports
a read interface. Use the Client#read method to read rows from
the database, and use its keys
option to pass unique identifiers as both
lists and ranges:
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"
results = db.read "users", [:id, :name], keys: 1..5
results.rows.each do |row|
puts "User #{row[:id]} is #{row[:name]}"
end
Using read-write transactions
When an operation might write data depending on values it reads, you should use a read-write transaction to perform the reads and writes atomically.
Suppose that sales of Albums(1, 1)
are lower than expected and you want
to move $200,000 from the marketing budget of Albums(2, 2)
to it, but
only if the budget of Albums(2, 2)
is at least $300,000.
Use Client#transaction to execute both reads and writes atomically at a single logical point in time. All changes are accumulated in memory until the block completes. Transactions will be automatically retried when possible. This operation makes separate API requests to begin and commit the transaction.
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"
db.transaction do |tx|
# Read the second album budget.
second_album_result = tx.read "Albums", ["marketing_budget"],
keys: [[2, 2]], limit: 1
second_album_row = second_album_result.rows.first
second_album_budget = second_album_row.values.first
transfer_amount = 200000
if second_album_budget < 300000
# Raising an exception will automatically roll back the transaction.
raise "The second album doesn't have enough funds to transfer"
end
# Read the first album's budget.
first_album_result = tx.read "Albums", ["marketing_budget"],
keys: [[1, 1]], limit: 1
first_album_row = first_album_result.rows.first
first_album_budget = first_album_row.values.first
# Update the budgets.
second_album_budget -= transfer_amount
first_album_budget += transfer_amount
puts "Setting first album's budget to #{first_album_budget} and the " \
"second album's budget to #{second_album_budget}."
# Update the rows.
rows = [
{singer_id: 1, album_id: 1, marketing_budget: first_album_budget},
{singer_id: 2, album_id: 2, marketing_budget: second_album_budget}
]
tx.update "Albums", rows
end
Using read-only transactions
Suppose you want to execute more than one read at the same timestamp. Read-only transactions observe a consistent prefix of the transaction commit history, so your application always gets consistent data. Because read-only transactions are much faster than locking read-write transactions, we strongly recommend that you do all of your transaction reads in read-only transactions if possible.
Use a Snapshot object to execute statements in a read-only transaction. The snapshot object is available via a block provided to Client#snapshot:
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
db = spanner.client "my-instance", "my-database"
db.snapshot do |snp|
results_1 = snp.execute "SELECT * FROM users"
results_1.rows.each do |row|
puts "User #{row[:id]} is #{row[:name]}"
end
# Perform another read using the `read` method. Even if the data
# is updated in-between the reads, the snapshot ensures that both
# return the same data.
results_2 = db.read "users", [:id, :name]
results_2.rows.each do |row|
puts "User #{row[:id]} is #{row[:name]}"
end
end
Deleting databases
Use Database#drop to delete a database:
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
database = spanner.database "my-instance", "my-database"
database.drop
Deleting instances
When you delete an instance, all databases within it are automatically deleted. (If you only delete databases and not your instance, you will still incur charges for the instance.) Use Instance#delete to delete an instance:
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new
instance = spanner.instance "my-instance"
instance.delete
Defined Under Namespace
Modules: Admin, V1 Classes: Client, ClientClosedError, Commit, Data, Database, DuplicateNameError, Fields, Instance, Policy, Project, Range, Results, Rollback, SessionLimitError, Snapshot, Status, Transaction
Constant Summary collapse
- VERSION =
"0.23.0"
Class Method Summary collapse
-
.new(project: nil, keyfile: nil, scope: nil, timeout: nil, client_config: nil) ⇒ Google::Cloud::Spanner::Project
Creates a new object for connecting to the Spanner service.
Class Method Details
.new(project: nil, keyfile: nil, scope: nil, timeout: nil, client_config: nil) ⇒ Google::Cloud::Spanner::Project
Creates a new object for connecting to the Spanner service. Each call creates a new connection.
For more information on connecting to Google Cloud see the Authentication Guide.
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/google/cloud/spanner.rb', line 366 def self.new project: nil, keyfile: nil, scope: nil, timeout: nil, client_config: nil project ||= Google::Cloud::Spanner::Project.default_project project = project.to_s # Always cast to a string fail ArgumentError, "project is missing" if project.empty? if keyfile.nil? credentials = Google::Cloud::Spanner::Credentials.default scope: scope else credentials = Google::Cloud::Spanner::Credentials.new( keyfile, scope: scope) end Google::Cloud::Spanner::Project.new( Google::Cloud::Spanner::Service.new( project, credentials, timeout: timeout, client_config: client_config)) end |