golang多适配器事务管理插件库go-transaction-manager的使用
Go Transaction Manager 使用指南
概述
Go Transaction Manager 是一个用于协调数据库事务边界的抽象层,支持多种数据库适配器。
支持的实现
- database/sql (Go 1.13+)
- jmoiron/sqlx (Go 1.13+)
- gorm (Go 1.18+)
- mongo-go-driver (Go 1.13+)
- go-redis/redis (Go 1.17+)
- pgx_v4 (Go 1.16+)
- pgx_v5 (Go 1.19+)
安装
go get github.com/avito-tech/go-transaction-manager/trm/v2
要安装特定数据库支持,例如 sqlx:
go get github.com/avito-tech/go-transaction-manager/drivers/sqlx/v2
使用示例
以下是一个完整的 SQLx 适配器使用示例:
package main
import (
"context"
"fmt"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"
trmsqlx "github.com/avito-tech/go-transaction-manager/drivers/sqlx/v2"
"github.com/avito-tech/go-transaction-manager/trm/v2/manager"
)
func main() {
// 初始化数据库连接
db, err := sqlx.Open("sqlite3", "file:test?mode=memory")
checkErr(err)
defer db.Close()
// 创建测试表
sqlStmt := `CREATE TABLE IF NOT EXISTS user (user_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, username TEXT);`
_, err = db.Exec(sqlStmt)
checkErr(err, sqlStmt)
// 初始化repository和事务管理器
r := newRepo(db, trmsqlx.DefaultCtxGetter)
ctx := context.Background()
trManager := manager.Must(trmsqlx.NewDefaultFactory(db))
u := &user{Username: "username"}
// 执行事务操作
err = trManager.Do(ctx, func(ctx context.Context) error {
checkErr(r.Save(ctx, u))
// 嵌套事务示例
return trManager.Do(ctx, func(ctx context.Context) error {
u.Username = "new_username"
return r.Save(ctx, u)
})
})
checkErr(err)
// 查询数据
userFromDB, err := r.GetByID(ctx, u.ID)
checkErr(err)
fmt.Println(userFromDB)
}
func checkErr(err error, args ...interface{}) {
if err != nil {
panic(fmt.Sprint(append([]interface{}{err}, args...)...))
}
}
// 定义repository结构体
type repo struct {
db *sqlx.DB
getter *trmsqlx.CtxGetter
}
func newRepo(db *sqlx.DB, c *trmsqlx.CtxGetter) *repo {
return &repo{db: db, getter: c}
}
// 定义用户模型
type user struct {
ID int64 `db:"user_id"`
Username string `db:"username"`
}
// 根据ID获取用户
func (r *repo) GetByID(ctx context.Context, id int64) (*user, error) {
query := "SELECT * FROM user WHERE user_id = ?;"
u := user{}
return &u, r.getter.DefaultTrOrDB(ctx, r.db).GetContext(ctx, &u, r.db.Rebind(query), id)
}
// 保存用户
func (r *repo) Save(ctx context.Context, u *user) error {
query := `UPDATE user SET username = :username WHERE user_id = :user_id;`
if u.ID == 0 {
query = `INSERT INTO user (username) VALUES (:username);`
}
res, err := sqlx.NamedExecContext(ctx, r.getter.DefaultTrOrDB(ctx, r.db), r.db.Rebind(query), u)
if err != nil {
return err
} else if u.ID != 0 {
return nil
} else if u.ID, err = res.LastInsertId(); err != nil {
return err
}
return err
}
关键特性说明
- 多数据库事务:需要在Settings中通过WithCtxKey设置CtxKey
- 嵌套事务:对于不同的事务管理器,需要使用ChainedMW
- 跳过回滚:可以使用ErrSkip或Skippable来跳过由于错误导致的事务回滚
最佳实践
- 使用
go get -u && go mod tidy
保持依赖更新 - 该库兼容最近两个Go版本,建议使用最新版本
- 对于生产环境,建议使用真实数据库进行集成测试
注意事项
- 该库使用了一些旧版依赖以支持旧版Go的向后兼容性
- 对于旧版Go支持,可能需要手动设置某些库的版本
更多关于golang多适配器事务管理插件库go-transaction-manager的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang多适配器事务管理插件库go-transaction-manager的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
go-transaction-manager 使用指南
go-transaction-manager 是一个用于 Golang 的多适配器事务管理库,它提供了统一的事务管理接口,支持多种数据库和存储引擎。
核心特性
- 支持多种适配器:PostgreSQL、MySQL、MongoDB、Redis 等
- 统一的事务管理接口
- 支持嵌套事务
- 上下文感知的事务管理
安装
go get github.com/avito-tech/go-transaction-manager
基本使用
1. 初始化事务管理器
import (
"context"
"database/sql"
"github.com/avito-tech/go-transaction-manager/trm"
"github.com/avito-tech/go-transaction-manager/trm/sqlx"
_ "github.com/lib/pq"
)
func main() {
// 初始化数据库连接
db, err := sql.Open("postgres", "postgres://user:password@localhost/dbname?sslmode=disable")
if err != nil {
panic(err)
}
// 创建事务管理器
trManager := sqlx.NewDefaultFactory(db)
// 使用事务管理器
ctx := context.Background()
err = trManager.Do(ctx, func(ctx context.Context) error {
// 业务逻辑代码
return nil
})
if err != nil {
// 处理错误
}
}
2. 嵌套事务示例
func processOrder(ctx context.Context, trManager trm.Manager) error {
return trManager.Do(ctx, func(ctx context.Context) error {
// 主事务逻辑
// 嵌套事务1
err := trManager.Do(ctx, func(ctx context.Context) error {
// 更新库存
return nil
})
if err != nil {
return err
}
// 嵌套事务2
err = trManager.Do(ctx, func(ctx context.Context) error {
// 创建订单
return nil
})
return err
})
}
3. 获取事务对象
func updateUser(ctx context.Context, trManager trm.Manager, userID int, name string) error {
return trManager.Do(ctx, func(ctx context.Context) error {
// 从上下文中获取事务对象
tr, ok := trm.FromContext(ctx)
if !ok {
return errors.New("transaction not found")
}
// 类型断言为具体的事务类型
sqlTr, ok := tr.(*sql.Tx)
if !ok {
return errors.New("invalid transaction type")
}
// 使用事务执行SQL
_, err := sqlTr.ExecContext(ctx, "UPDATE users SET name = $1 WHERE id = $2", name, userID)
return err
})
}
多适配器支持
1. MongoDB 适配器示例
import (
"go.mongodb.org/mongo-driver/mongo"
"github.com/avito-tech/go-transaction-manager/trm/mongo"
)
func main() {
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
panic(err)
}
trManager := mongo.NewDefaultFactory(client)
err = trManager.Do(context.Background(), func(ctx context.Context) error {
collection := client.Database("test").Collection("users")
_, err := collection.InsertOne(ctx, bson.M{"name": "John"})
return err
})
}
2. Redis 适配器示例
import (
"github.com/redis/go-redis/v9"
"github.com/avito-tech/go-transaction-manager/trm/redis"
)
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
trManager := redis.NewDefaultFactory(rdb)
err := trManager.Do(context.Background(), func(ctx context.Context) error {
err := rdb.Set(ctx, "key", "value", 0).Err()
return err
})
}
高级配置
1. 自定义事务设置
func main() {
db, _ := sql.Open("postgres", "postgres://...")
// 自定义事务设置
settings := sqlx.NewSettings(
sqlx.WithIsolationLevel(sql.LevelSerializable),
sqlx.WithReadOnly(false),
)
trManager := sqlx.New(db, settings)
// 使用事务管理器...
}
2. 事务传播行为
func main() {
db, _ := sql.Open("postgres", "postgres://...")
trManager := sqlx.NewDefaultFactory(db)
ctx := context.Background()
// REQUIRED (默认): 如果存在事务则加入,否则新建
err := trManager.Do(ctx, func(ctx context.Context) error {
// 业务逻辑
// REQUIRES_NEW: 总是新建事务
return trManager.Do(trm.NewPropagation(ctx, trm.PropagationRequiresNew), func(ctx context.Context) error {
// 独立事务逻辑
return nil
}
})
}
最佳实践
- 事务边界:合理划分事务边界,避免过长事务
- 错误处理:正确处理事务中的错误,确保事务能够正确回滚
- 上下文传递:始终传递上下文,确保事务能够正确传播
- 隔离级别:根据业务需求选择合适的隔离级别
总结
go-transaction-manager 提供了统一的事务管理接口,简化了多数据源环境下的事务管理。通过适配器模式,它可以轻松集成到现有项目中,并提供灵活的事务控制能力。