sqldb

package
v0.0.0-...-e5591e2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 24, 2023 License: MIT Imports: 22 Imported by: 0

README

sqldb

sqldb 主要解决以下问题:

  • 加载数据库配置
  • 记录 sql 执行日志
  • 上报 opentracing 追踪数据
  • 汇总 prometheus 监控指标

核心思想是用github.com/ngrok/sqlmw把现有的database/sql驱动包起来, 拦截所有数据库操作进行观察。

配置

框架默认支持 sqlite 和 mysql。

每个数据库的配置需要指定一个名字,并添加SQLDB_DSN_前缀。

# sqlite 配置示例
SQLDB_DSN_lite1 = "file:///tmp/foo.db"
# mysql 配置示例
SQLDB_DSN_mysql1 = "username:password@protocol(address)/dbname?param=value"

不同的驱动需要不同的配置内容:

使用

框架通过sqldb.Get(name)函数获取数据库实例,入参是配置名(去掉前缀), 返回的是*sqlx.DB对象。

框架会根据配置内容自动识别数据库驱动。

import "github.com/go-kiss/sniper/pkg/sqldb"

db := sqldb.Get(ctx, "name")
db.ExecContext(ctx, "delete from ...")

ORM

sqldb 提供简单的 Insert/Update/StructScan 方法,替换常用的 ORM 使用场景。

所有的模型对象都必须实现 Modler 接口,支持查询所属的表名和主键字段名。

比如我们定义一个 user 对象:

type user struct {
	ID      int
	Name    string
	Age     int
	Created time.Time
}
func (u *user) TableName() string { return "users" }
func (u *user) KeyName() string   { return "id" }

保存对象:

u := {Name:"foo", Age:18, Created:time.Now()}
result, err := db.Insert(&u)

更新对象:

u.Name = "bar"
result, err := db.Update(&u)

查询对象:

var u user
err := db.Get(&u, "select * from users where id = ?", id)

现有问题

受限于 database/sql 驱动的设计,我们无法在提交或者回滚事务的时候确定总耗时。

目前只能监控 begin/commit/rollback 单个查询耗时,而非事务总耗时。

database/sql 不支持添加 hooks,而使用 sql.Regster 只能进行全局注册。为了实现 不同数据库实例注册不同 hooks 的效果(主要用于保存数据库配置名字),我们为每个 数据库配置分别注册 sql.Driver 实例。

添加新驱动

如果想添加 sqlite 和 mysql 之外的数据库驱动(比如 postgres),需要初始化 driverName 和 driver 两个变量。driverName 中应该包含数据库配置名(实例名)。

driverName = "db-sqlite:" + name
driver = sqlmw.Driver(&sqlite.Driver{}, observer{name: name})

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DB

type DB struct {
	*sqlx.DB
}

DB 扩展 sqlx.DB

func Get

func Get(ctx context.Context, name string) *DB

Get 获取数据库实例

db := sqldb.Get(ctx, "foo") db.ExecContext(ctx, "select ...")

func (*DB) BeginTxx

func (db *DB) BeginTxx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)

BeginTxx 封装 sqlx.DB.BeginTxx,返回自定义的 *Tx

func (*DB) Beginx

func (db *DB) Beginx() (*Tx, error)

Beginx 封装 sqlx.DB.Beginx,返回自定义的 *Tx

func (*DB) GetMapper

func (db *DB) GetMapper() *reflectx.Mapper

添加 GetMapper 方法,方便与 Tx 统一

func (*DB) Insert

func (db *DB) Insert(m Modeler) (sql.Result, error)

func (*DB) InsertContext

func (db *DB) InsertContext(ctx context.Context, m Modeler) (sql.Result, error)

InsertContext 生成并执行 insert 语句

func (*DB) MustBegin

func (db *DB) MustBegin() *Tx

MustBegin 封装 sqlx.DB.MustBegin,返回自定义的 *Tx

func (*DB) Update

func (db *DB) Update(m Modeler) (sql.Result, error)

func (*DB) UpdateContext

func (db *DB) UpdateContext(ctx context.Context, m Modeler) (sql.Result, error)

UpdateContext 生成并执行 update 语句

type Modeler

type Modeler interface {
	// TableName 返回表名
	TableName() string
	// TableName 返回主键字段名
	KeyName() string
}

Modeler 接口提供查询模型的表结构信息 所有模型都需要实现本接口

type Tx

type Tx struct {
	*sqlx.Tx
}

Tx 扩展 sqlx.Tx

func (*Tx) GetMapper

func (tx *Tx) GetMapper() *reflectx.Mapper

添加 GetMapper 方法,方便与 DB 统一

func (*Tx) Insert

func (tx *Tx) Insert(m Modeler) (sql.Result, error)

func (*Tx) InsertContext

func (tx *Tx) InsertContext(ctx context.Context, m Modeler) (sql.Result, error)

InsertContext 生成并执行 insert 语句

func (*Tx) Update

func (tx *Tx) Update(m Modeler) (sql.Result, error)

func (*Tx) UpdateContext

func (tx *Tx) UpdateContext(ctx context.Context, m Modeler) (sql.Result, error)

UpdateContext 生成并执行 update 语句

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL