Spanner客户端库 #

一、客户端库概述 #

1.1 支持的语言 #

text
Spanner客户端库支持:
├── Java
├── Python
├── Go
├── Node.js
├── C++
├── C#
├── PHP
├── Ruby
└── REST API

1.2 客户端功能 #

text
客户端库功能:
├── 连接管理
├── 会话池
├── 事务处理
├── 查询执行
├── Mutation操作
├── 错误处理
└── 重试机制

二、Java客户端 #

2.1 安装 #

xml
<!-- Maven -->
<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-spanner</artifactId>
    <version>6.45.0</version>
</dependency>
gradle
// Gradle
implementation 'com.google.cloud:google-cloud-spanner:6.45.0'

2.2 基本使用 #

java
import com.google.cloud.spanner.SpannerOptions;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.Statement;
import com.google.cloud.spanner.ResultSet;

public class SpannerExample {
    
    public static void main(String[] args) {
        // 创建Spanner客户端
        SpannerOptions options = SpannerOptions.newBuilder().build();
        Spanner spanner = options.getService();
        
        // 获取数据库客户端
        DatabaseId dbId = DatabaseId.of("my-project", "my-instance", "my-database");
        DatabaseClient client = spanner.getDatabaseClient(dbId);
        
        // 执行查询
        try (ResultSet rs = client.singleUse()
                .executeQuery(Statement.of("SELECT * FROM users LIMIT 10"))) {
            while (rs.next()) {
                System.out.println(rs.getLong("user_id") + ": " + rs.getString("name"));
            }
        }
        
        spanner.close();
    }
}

2.3 事务处理 #

java
import com.google.cloud.spanner.TransactionRunner;
import com.google.cloud.spanner.Mutation;
import com.google.cloud.spanner.Key;
import com.google.cloud.spanner.Struct;

// 读写事务
TransactionRunner runner = client.readWriteTransaction();
runner.run(transaction -> {
    // 读取数据
    Struct row = transaction.readRow("users", 
        Key.of(1L), Arrays.asList("name", "email"));
    
    // 更新数据
    transaction.buffer(Mutation.newUpdateBuilder("users")
        .set("user_id").to(1L)
        .set("name").to("John Updated")
        .build());
    
    return null;
});

// 只读事务
try (ReadOnlyTransaction transaction = client.readOnlyTransaction()) {
    ResultSet rs = transaction.executeQuery(
        Statement.of("SELECT * FROM users"));
    // 处理结果
}

2.4 Mutation操作 #

java
import com.google.cloud.spanner.Mutation;

// 插入
Mutation insert = Mutation.newInsertBuilder("users")
    .set("user_id").to(1L)
    .set("name").to("John Doe")
    .set("email").to("john@example.com")
    .build();

// 更新
Mutation update = Mutation.newUpdateBuilder("users")
    .set("user_id").to(1L)
    .set("name").to("John Updated")
    .build();

// 删除
Mutation delete = Mutation.delete("users", Key.of(1L));

// 批量写入
List<Mutation> mutations = Arrays.asList(insert, update);
client.write(mutations);

三、Python客户端 #

3.1 安装 #

bash
pip install google-cloud-spanner

3.2 基本使用 #

python
from google.cloud import spanner

# 创建客户端
spanner_client = spanner.Client(project='my-project')
instance = spanner_client.instance('my-instance')
database = instance.database('my-database')

# 执行查询
with database.snapshot() as snapshot:
    results = snapshot.execute_sql(
        "SELECT * FROM users LIMIT 10"
    )
    
    for row in results:
        print(f"{row[0]}: {row[1]}")

3.3 事务处理 #

python
# 读写事务
def update_user(database, user_id, new_name):
    def transaction_func(transaction):
        # 读取数据
        row = list(transaction.read(
            "users", ["name", "email"],
            spanner.KeySet([spanner.Key([user_id])])
        ))[0]
        
        # 更新数据
        transaction.update(
            table="users",
            columns=("user_id", "name"),
            values=[(user_id, new_name)]
        )
    
    database.run_in_transaction(transaction_func)

# 只读事务
with database.snapshot() as snapshot:
    results = snapshot.execute_sql("SELECT * FROM users")

3.4 Mutation操作 #

python
# 批量插入
def batch_insert(database, users):
    with database.batch() as batch:
        batch.insert(
            table="users",
            columns=("user_id", "name", "email"),
            values=users
        )

# 批量更新
def batch_update(database, users):
    with database.batch() as batch:
        batch.update(
            table="users",
            columns=("user_id", "name"),
            values=users
        )

# 批量删除
def batch_delete(database, user_ids):
    keys = [spanner.Key([uid]) for uid in user_ids]
    with database.batch() as batch:
        batch.delete("users", spanner.KeySet(keys=keys))

四、Go客户端 #

4.1 安装 #

bash
go get cloud.google.com/go/spanner

4.2 基本使用 #

go
package main

import (
    "context"
    "fmt"
    "cloud.google.com/go/spanner"
)

func main() {
    ctx := context.Background()
    
    // 创建客户端
    dbPath := "projects/my-project/instances/my-instance/databases/my-database"
    client, err := spanner.NewClient(ctx, dbPath)
    if err != nil {
        panic(err)
    }
    defer client.Close()
    
    // 执行查询
    iter := client.Single().Query(ctx, spanner.Statement{
        SQL: "SELECT * FROM users LIMIT 10",
    })
    defer iter.Stop()
    
    for {
        row, err := iter.Next()
        if err == iterator.Done {
            break
        }
        if err != nil {
            panic(err)
        }
        
        var userID int64
        var name string
        if err := row.Columns(&userID, &name); err != nil {
            panic(err)
        }
        fmt.Printf("%d: %s\n", userID, name)
    }
}

4.3 事务处理 #

go
// 读写事务
func updateUser(ctx context.Context, client *spanner.Client, userID int64, newName string) error {
    _, err := client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error {
        // 读取数据
        row, err := txn.ReadRow(ctx, "users", spanner.Key{userID}, []string{"name"})
        if err != nil {
            return err
        }
        
        // 更新数据
        m := spanner.Update("users", 
            []string{"user_id", "name"}, 
            []interface{}{userID, newName})
        
        return txn.BufferWrite([]*spanner.Mutation{m})
    })
    return err
}

// 只读事务
func readOnlyTransaction(ctx context.Context, client *spanner.Client) error {
    ro := client.ReadOnlyTransaction()
    defer ro.Close()
    
    iter := ro.Query(ctx, spanner.Statement{
        SQL: "SELECT * FROM users",
    })
    defer iter.Stop()
    
    // 处理结果...
    return nil
}

4.4 Mutation操作 #

go
// 插入
func insertUser(ctx context.Context, client *spanner.Client, userID int64, name, email string) error {
    m := spanner.Insert("users",
        []string{"user_id", "name", "email"},
        []interface{}{userID, name, email},
    )
    
    _, err := client.Apply(ctx, []*spanner.Mutation{m})
    return err
}

// 批量操作
func batchInsert(ctx context.Context, client *spanner.Client, users []User) error {
    var mutations []*spanner.Mutation
    
    for _, u := range users {
        m := spanner.Insert("users",
            []string{"user_id", "name", "email"},
            []interface{}{u.ID, u.Name, u.Email},
        )
        mutations = append(mutations, m)
    }
    
    _, err := client.Apply(ctx, mutations)
    return err
}

五、Node.js客户端 #

5.1 安装 #

bash
npm install @google-cloud/spanner

5.2 基本使用 #

javascript
const { Spanner } = require('@google-cloud/spanner');

// 创建客户端
const spanner = new Spanner({
    projectId: 'my-project',
});

const instance = spanner.instance('my-instance');
const database = instance.database('my-database');

// 执行查询
async function queryUsers() {
    const [rows] = await database.run({
        sql: 'SELECT * FROM users LIMIT 10',
    });
    
    rows.forEach(row => {
        console.log(`${row.user_id}: ${row.name}`);
    });
}

queryUsers();

5.3 事务处理 #

javascript
// 读写事务
async function updateUser(userId, newName) {
    await database.runTransactionAsync(async (transaction) => {
        // 读取数据
        const [rows] = await transaction.run({
            sql: 'SELECT name FROM users WHERE user_id = @userId',
            params: { userId: userId },
        });
        
        // 更新数据
        await transaction.runUpdate({
            sql: 'UPDATE users SET name = @name WHERE user_id = @userId',
            params: { name: newName, userId: userId },
        });
        
        await transaction.commit();
    });
}

// 只读事务
async function readOnlyTransaction() {
    const [rows] = await database.run({
        sql: 'SELECT * FROM users',
    });
    // 处理结果
}

5.4 Mutation操作 #

javascript
// 批量插入
async function batchInsert(users) {
    const mutations = users.map(user => ({
        insert: {
            table: 'users',
            columns: ['user_id', 'name', 'email'],
            values: [[user.id.toString(), user.name, user.email]],
        },
    }));
    
    await database.write(mutations);
}

六、连接池配置 #

6.1 Java连接池 #

java
import com.google.cloud.spanner.SpannerOptions;
import com.google.cloud.spanner.SessionPoolOptions;

SessionPoolOptions poolOptions = SessionPoolOptions.newBuilder()
    .setMinSessions(10)
    .setMaxSessions(100)
    .setIncStep(5)
    .build();

SpannerOptions options = SpannerOptions.newBuilder()
    .setSessionPoolOption(poolOptions)
    .build();

6.2 Python连接池 #

python
from google.cloud import spanner

client = spanner.Client(
    project='my-project',
    client_options={
        'session_pool_options': {
            'min_sessions': 10,
            'max_sessions': 100,
        }
    }
)

6.3 Go连接池 #

go
import "cloud.google.com/go/spanner"

config := spanner.ClientConfig{
    SessionPoolConfig: spanner.SessionPoolConfig{
        MinOpened: 10,
        MaxOpened: 100,
    },
}
client, err := spanner.NewClientWithConfig(ctx, dbPath, config)

七、错误处理 #

7.1 Java错误处理 #

java
import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.ErrorCode;

try {
    client.write(mutations);
} catch (SpannerException e) {
    switch (e.getErrorCode()) {
        case ALREADY_EXISTS:
            System.err.println("主键冲突");
            break;
        case NOT_FOUND:
            System.err.println("数据不存在");
            break;
        case DEADLINE_EXCEEDED:
            System.err.println("操作超时");
            break;
        case ABORTED:
            System.err.println("事务被中止");
            break;
        default:
            System.err.println("其他错误: " + e.getMessage());
    }
}

7.2 Python错误处理 #

python
from google.cloud.spanner import exceptions

try:
    database.run_in_transaction(transaction_func)
except exceptions.AlreadyExists:
    print("主键冲突")
except exceptions.NotFound:
    print("数据不存在")
except exceptions.DeadlineExceeded:
    print("操作超时")
except exceptions.Aborted:
    print("事务被中止")

八、最佳实践 #

8.1 连接管理 #

text
连接管理建议:
├── 使用连接池
├── 合理设置池大小
├── 及时关闭连接
├── 复用客户端实例
└── 监控连接状态

8.2 事务处理 #

text
事务处理建议:
├── 减少事务大小
├── 使用只读事务
├── 处理冲突重试
├── 设置合理超时
└── 监控事务性能

8.3 性能优化 #

text
性能优化建议:
├── 使用批量操作
├── 使用参数化查询
├── 避免热点主键
├── 使用交错表
└── 监控客户端性能

九、总结 #

客户端库选择:

语言 特点
Java 企业级应用首选
Python 数据分析、脚本
Go 高性能服务
Node.js Web应用

最佳实践:

text
1. 使用连接池
   └── 合理配置池大小

2. 使用参数化查询
   └── 防止SQL注入

3. 处理错误和重试
   └── 保证可靠性

4. 监控客户端性能
   └── 及时发现问题

5. 复用客户端实例
   └── 减少创建开销

下一步,让我们学习Spanner迁移!

最后更新:2026-03-27