golang Yandex Database原生驱动与database/sql接口插件库ydb-go-sdk的使用
golang Yandex Database原生驱动与database/sql接口插件库ydb-go-sdk的使用
概述
ydb-go-sdk
是一个纯Go实现的YDB原生驱动,同时支持database/sql
接口。YDB是一个开源的分布式SQL数据库,结合了高可用性、可扩展性与严格一致性和ACID事务。
支持的Go版本
ydb-go-sdk
支持Go官方发布策略支持的所有Go版本,即最新的两个Go版本(或更多,但不保证额外版本的支持)。
安装
go get -u github.com/ydb-platform/ydb-go-sdk/v3
使用示例
连接到YDB
db, err := ydb.Open(ctx, "grpc://localhost:2136/local")
if err != nil {
log.Fatal(err)
}
使用Query服务客户端执行SELECT查询
// 在错误时进行重试操作
err := db.Query().Do( // 在错误时进行重试操作
ctx, // 上下文管理从Do退出
func(ctx context.Context, s query.Session) (err error) { // 重试操作
streamResult, err := s.Query(ctx, `SELECT 42 as id, "myStr" as myStr;`)
if err != nil {
return err // 用于驱动自动重试
}
defer func() { _ = streamResult.Close(ctx) }() // 清理资源
for rs, err := range streamResult.ResultSets(ctx) {
if err != nil {
return err
}
for row, err := range rs.Rows(ctx) {
if err != nil {
return err
}
type myStruct struct {
Id int32 `sql:"id"`
Str string `sql:"myStr"`
}
var s myStruct
if err = row.ScanStruct(&s); err != nil {
return err // 通常扫描错误不可重试,返回给驱动检查错误
}
}
}
return nil
},
query.WithIdempotent(),
)
if err != nil {
log.Fatal(err)
}
使用database/sql接口
import (
"context"
"database/sql"
"log"
_ "github.com/ydb-platform/ydb-go-sdk/v3"
)
...
db, err := sql.Open("ydb", "grpc://localhost:2136/local")
if err != nil {
log.Fatal(err)
}
defer db.Close() // 清理资源
var (
id int32
myStr string
)
row := db.QueryRowContext(context.TODO(), `SELECT 42 as id, "my string" as myStr`)
if err = row.Scan(&id, &myStr); err != nil {
log.Printf("select failed: %v", err)
return
}
log.Printf("id = %d, myStr = \"%s\"", id, myStr)
认证凭据
驱动提供了几种为YDB创建凭据的方式:
ydb.WithAnonymousCredentials()
(默认启用,除非另有指定)ydb.WithAccessTokenCredentials("token")
ydb.WithStaticCredentials("user", "password")
ydb.WithOauth2TokenExchangeCredentials()
和ydb.WithOauth2TokenExchangeCredentialsFile(configFilePath)
- 作为连接字符串的一部分,如
grpcs://user:password@endpoint/database
环境变量
ydb-go-sdk
支持以下环境变量,这些变量会重新定义驱动的默认行为:
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
YDB_SSL_ROOT_CERTIFICATES_FILE |
string |
证书文件路径 | |
YDB_LOG_SEVERITY_LEVEL |
string |
quiet |
内部驱动日志的严重级别。支持:trace , debug , info , warn , error , fatal , quiet |
YDB_LOG_DETAILS |
string |
.* |
用于查找内部日志记录器的正则表达式 |
GRPC_GO_LOG_VERBOSITY_LEVEL |
integer |
设置为99 以查看grpc日志 |
|
GRPC_GO_LOG_SEVERITY_LEVEL |
string |
设置为info 以查看grpc日志 |
更多关于golang Yandex Database原生驱动与database/sql接口插件库ydb-go-sdk的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang Yandex Database原生驱动与database/sql接口插件库ydb-go-sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Yandex Database (YDB) 在 Golang 中的使用
Yandex Database (YDB) 是 Yandex 开发的分布式数据库系统,支持 SQL 查询和 ACID 事务。在 Golang 中,我们可以通过两种方式连接 YDB:
- 原生驱动
ydb-go-sdk
- 通过
database/sql
接口的标准方式
1. 原生驱动 ydb-go-sdk 使用
安装
go get github.com/ydb-platform/ydb-go-sdk/v3
基本示例
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/ydb-platform/ydb-go-sdk/v3"
"github.com/ydb-platform/ydb-go-sdk/v3/table"
"github.com/ydb-platform/ydb-go-sdk/v3/table/options"
"github.com/ydb-platform/ydb-go-sdk/v3/table/result"
"github.com/ydb-platform/ydb-go-sdk/v3/table/types"
)
func main() {
ctx := context.Background()
// 创建连接
db, err := ydb.Open(ctx,
"grpcs://ydb.serverless.yandexcloud.net:2135/ru-central1/b1g8skpblkos03malf3s/etn02qso4h3isjb00te1",
ydb.WithAccessTokenCredentials("your-access-token"),
)
if err != nil {
log.Fatal(err)
}
defer db.Close(ctx)
// 创建表
err = createTable(ctx, db.Table())
if err != nil {
log.Fatal(err)
}
// 插入数据
err = upsertData(ctx, db.Table())
if err != nil {
log.Fatal(err)
}
// 查询数据
err = selectData(ctx, db.Table())
if err != nil {
log.Fatal(err)
}
}
func createTable(ctx context.Context, c table.Client) error {
return c.Do(ctx,
func(ctx context.Context, s table.Session) error {
return s.CreateTable(ctx, "example",
options.WithColumn("id", types.TypeUint64),
options.WithColumn("name", types.TypeUTF8),
options.WithColumn("created_at", types.TypeTimestamp),
options.WithPrimaryKeyColumn("id"),
)
},
)
}
func upsertData(ctx context.Context, c table.Client) error {
return c.Do(ctx,
func(ctx context.Context, s table.Session) error {
_, _, err := s.Execute(ctx,
table.DefaultTxControl(),
"DECLARE $id AS Uint64; DECLARE $name AS Utf8; DECLARE $created_at AS Timestamp;"+
"UPSERT INTO example (id, name, created_at) VALUES ($id, $name, $created_at);",
table.NewQueryParameters(
table.ValueParam("$id", types.Uint64Value(1)),
table.ValueParam("$name", types.UTF8Value("Alice")),
table.ValueParam("$created_at", types.TimestampValueFromTime(time.Now())),
),
)
return err
},
)
}
func selectData(ctx context.Context, c table.Client) error {
return c.Do(ctx,
func(ctx context.Context, s table.Session) error {
_, res, err := s.Execute(ctx,
table.DefaultTxControl(),
"SELECT id, name, created_at FROM example WHERE id = $id;",
table.NewQueryParameters(
table.ValueParam("$id", types.Uint64Value(1)),
),
)
if err != nil {
return err
}
defer res.Close()
for res.NextResultSet(ctx) {
for res.NextRow() {
var (
id uint64
name string
createdAt time.Time
)
if err := res.Scan(&id, &name, &createdAt); err != nil {
return err
}
fmt.Printf("id: %d, name: %q, created_at: %v\n", id, name, createdAt)
}
}
return res.Err()
},
)
}
2. 通过 database/sql 接口使用
安装
go get github.com/ydb-platform/ydb-go-sdk/v3
go get github.com/ydb-platform/ydb-go-sdk-auth-environ
基本示例
package main
import (
"context"
"database/sql"
"fmt"
"log"
"time"
"github.com/ydb-platform/ydb-go-sdk/v3"
ydbsql "github.com/ydb-platform/ydb-go-sdk/v3/sql"
)
func main() {
ctx := context.Background()
// 创建连接
dsn := "grpcs://ydb.serverless.yandexcloud.net:2135/ru-central1/b1g8skpblkos03malf3s/etn02qso4h3isjb00te1"
nativeDriver, err := ydb.Open(ctx, dsn)
if err != nil {
log.Fatal(err)
}
defer nativeDriver.Close(ctx)
// 创建 database/sql 连接
connector, err := ydbsql.Connector(nativeDriver)
if err != nil {
log.Fatal(err)
}
db := sql.OpenDB(connector)
defer db.Close()
// 创建表
_, err = db.ExecContext(ctx, `
CREATE TABLE IF NOT EXISTS example_sql (
id Uint64,
name Utf8,
created_at Timestamp,
PRIMARY KEY (id)
)
`)
if err != nil {
log.Fatal(err)
}
// 插入数据
_, err = db.ExecContext(ctx, `
UPSERT INTO example_sql (id, name, created_at) VALUES (?, ?, ?)
`, 1, "Bob", time.Now())
if err != nil {
log.Fatal(err)
}
// 查询数据
rows, err := db.QueryContext(ctx, `
SELECT id, name, created_at FROM example_sql WHERE id = ?
`, 1)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var (
id uint64
name string
createdAt time.Time
)
if err := rows.Scan(&id, &name, &createdAt); err != nil {
log.Fatal(err)
}
fmt.Printf("id: %d, name: %q, created_at: %v\n", id, name, createdAt)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
}
两种方式的比较
-
原生驱动 (ydb-go-sdk)
- 提供更完整的 YDB 功能支持
- 支持更精细的控制和优化
- 性能更好
- 语法更接近 YDB 原生接口
-
database/sql 接口
- 更符合标准 SQL 接口习惯
- 可以更容易地与其他数据库切换
- 代码更简洁
- 功能可能受限于标准接口的限制
最佳实践建议
- 如果项目需要充分利用 YDB 的特定功能,建议使用原生驱动
- 如果项目需要数据库抽象层或可能切换数据库,建议使用 database/sql 接口
- 对于新项目,可以从 database/sql 接口开始,需要时再切换到原生驱动
两种方式可以混合使用,因为 ydb-go-sdk 提供了 Connector 接口,可以在同一个应用中同时使用两种方式访问 YDB。