这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记
一、理解database/sql
databse/sql 基本用法,设计原理,基础概念
1.0 基本概念
databse/sql包:golang标准库提供的和数据库交互的包,其理念是对不同的数据库实现提供一套一致的接口给用户使用
DSN:Data Source Name,数据库名称,用于描述与数据连接的关联数据结构
1.1 基本用法
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func main() {
// 使用 driver + DSN 初始化 DB 连接
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname")
// 执行一条 SQL,通过 rows 取回 返回数据
rows, err := db.Query("select id, name from users wherer id = ?", 1)
if err != nil {
// xxx
}
// 处理完毕,释放
defer rows.Close()
// jinzhu:上面这句其实有问题, err直接close,可能丢失错误信息
// jinzhu大佬 更好的写法
// defer func() {
// err = rows.Close()
// }
var users []User
for rows.Next() {
var userUser
err := rows.Scan(&user.ID, &user.Name)
if err != nil {
// ...
}
users = append(users, user)
}
// 这个错误处理也很重要
if rows.Err() != nil {
// ...
}
}
连接池
for i := 0 i < maxBadConRetries; i++ {
dc, err := db.conn(ctx, strategy)
// 有空闲连接 -> reuse - max life time
// 新建连接 -> max open...
defer dc.db.putConn(dc, err, true)
// validateConnction 有无错误
// max life time, max idle conn 检查
// 连接实现 driver。Queryer, driver.Execer 等 interface
if err == nil {
err = dc.ci.Qiery(sql, args...)
}
isBadConn = errors.Is(err, driver.ErrBadConn)
if !isBadConn {
break
}
}
jinzhu 大佬:
- maxBadConnRetries:不可配置,如果能配置就更好了
- 有可能sql已经被执行,但是仍然产生错误,出发重试,sql执行多次
1.2 设计原理
对上层应用提供操作接口,对下层数据库提供连接接口和操作接口,让实现方来实现
值得一提的是,使用了池化技术,对比较贵重的资源(数据库连接)
二、GORM使用简介
GORM 基本用法,Model定义,惯例约定,关联操作
三、GORM设计原理
SQL生成,插件扩展,ConnPool、Dialector
- SQL 是怎么生成的
- 插件是怎么工作的
- ConnPool是什么
- Dialector
3.0 GORM的位置
3.1 SQL是怎样生成的
从上面的图我们可以看到,一个SQL语句是由很多的子句构成的,以下是使用gorm生成SQL执行的代码和子句的对应关系
其中,chain method会对整个gorm statement起到筛选的作用,而 finisher method会决定最终的类型以及执行的细节。jinzhu 大佬:这么设计是为了三件事:
- 自定义子句
- 拓展子句
- 选择子句:可以在不同的数据库对应的sql中使用对应的sql
3.2 插件如何工作
3.3 ConnPool
有了ConnPool这个接口口,我们可以做读写分离,自定义编排存储流程的插件,自定义事务配置,对接第三方api代替sql进行存储等等操作,总的来说就是通过一个中间层干预了存储层和代码层的对接
3.4 Dialector
实际使用数据库的时候,一些参数的配置往往能四两拨千斤,对性能优化起到不小的作用,但是查阅各种文档学习这些细枝末节未免太过头重脚轻,Dialector是gorm提供的一个接口,用户可以通过实现该接口,在使用dsn连接数据源的时候加入一些配置项,从而达到减少配置的效果
四、GORM最佳实践
GORM最佳实践、企业级开发、FAQ
- 数据序列化 与 SQL表达式
- 批量数据操作
- 代码复用,分库分表,Sharding
- 混沌工程,压测
- Logger,Trace
- Migrator
- Gen 代码生成 / Raw SQL
- 安全