gotx - 一个Golang数据库事务管理器

95 阅读2分钟

github.com/oligo/gotx

gotx其实是好几年前的一个项目了,只不过当初只是快速做了一些概念验证,实现了一个基本可用的Demo。近两年来自己也在项目里引入使用,发现还是存在挺多问题的,但是一直没有时间去改进,于是就一直在烂尾的状态。

近期因为一个在做的项目存储模块从key-value迁移到RDBMS, 于是又把gotx捡起来了。使用过程中也发现了不少问题,同时也回顾了下当初的设计思路,前前后后花了几天时间把这些问题都解决了。到目前也真的到了一个可用的状态了,遂想着分享出来,供大家参考,也欢迎大家使用、反馈。

gotx是什么

如标题所言,gotx是一个数据库事务管理器,其所做的事情只有两个:

  1. 提供一套简单的API,让开发者能轻松管理数据库事务(支持nested transactions).

  2. 提供类似sqlx的CURD API,让开发者能快速编写数据访问逻辑。

Java生态下,事务管理是非常轻松的一件事,特别是在Spring框架下。Golang生态下的一些ORM基本都有类似的事务管理方式,但是对于不像使用ORM的人来说,选择并不多。Gotx的定位和Sqlx类似,只提供自动事务管理功能和CURD API,你也可以混合使用sqlx/sql接口,不会有太多心里负担。

gotx实现了什么

gotx实现的是自动事务管理,使用方式很简单,基本接口使用如下所示:

 import (
	"context"
	"database/sql"
	"fmt"

	"github.com/jmoiron/sqlx"
	"github.com/oligo/gotx"
)

// account model as an example here.
// Gotx use sqlx db tag here to do column mapping
type Account struct {
	ID   int64  `db:"id"`
	Name string `db:"name"`
    Articles []*Article
}

type Article struct {
    ID   int64  `db:"id"`
	Content string `db:"content"`
}

func main() {
	//using a DNS for mysql here
	dsn := "root:12345@tcp(127.0.0.1:3306)/db"

	db, err := sqlx.Connect("mysql", dsn)

	if err != nil {
		panic(err)
	}

	txManager := gotx.NewTxManager(db)

	// declares the tx options here. Please note that if options is omitted,
	// the default option is used. By default we use PropagationRequired for propagation
	// and RepeatableRead for isolation level.
	opts := &gotx.Options{
		Propagation:    gotx.PropagationRequired,
		IsolationLevel: sql.LevelRepeatableRead,
	}

	// use userID=10 for example
	userID := 10
	var account Account
	_ = txManager.Exec(context.Background(), func(tx *gotx.Transaction) error {
		// for more query method, please consult the godoc of this project
		err := tx.GetOne(&account, "select id, name from account where id=?", userID)
		if err != nil {
			return err
		}

        var articles []*Article
        // execute a nested transaction
        err = txManager.Exec(context.Background(), func(tx *gotx.Transaction) error {
            // for more query method, please consult the godoc of this project
            err := tx.Select(&articles, "select * from article where user_id=?", userID)
            if err != nil {
                return err
            }

            account.Articles = articles
            return nil
        }, opts)

		// Any error returned in this function will trigger the rollback of the transaction.
		return err

	}, opts)

}

更多使用方式请参考godoc或项目代码:

github.com/oligo/gotx
pkg.go.dev/github.com/…