- 理解database / sql
- 基本用法
- 常见错误:事务没有commit、close,因为有时候异常会使close无法正常执行,所以需要手动关闭
- 可以在import的时候添加不同数据库的driver,这样就可以用同样的方式同样的代码去支持不一样的数据库
- 设计原理
应用程序
<--api操作接口--> 上层应用
database / sql连接池
<--连接接口/操作接口--> 数据库Driver
数据库
- 连接池
- 配置
- func (db *DB) SetConnMaxIdleTime(d time.Duration)
- func (db *DB) SetConnMaxLifeTime(d time.Duration)
- func (da *DB) SetMaxIdleConns(n int)
- func (da *DB) SetMaxOpenConns(n int)
- 状态
- func (db *DB) Stats() DBStats
- DB连接的类型
- 直接连接 / Conn
- 预编译 / Stmt
- 事务 / Tx
- 处理返回数据的方式
- Exec /ExecXontext -> Result
- Query / QueryContext -> Rows(Columns)
- QueryRow / QueryRowContext -> Row(Rows 简化)
- 配置
- GORM使用简介
设计简洁、功能强大、自由扩展的全功能ORM
- 基本用法 - CRUD
- 读取
- 更新某个/多个字段
- 批量更新
- 删除
- 模型定义 - 惯例约束
- 表名为struct name的snake_cases复数格式
- 字段名为field name的snake_case单数格式
- ID /Id字段为主键,如果为数字,则为自增主键
- CreatedAt字段,创建时,保存当前时间
- UpdateAt字段,创建、更新时,保存当前时间
- gorm。DeletedAt字段时,默认开启soft delete模式
- 关联操作
- CRUD
- Preload / Joins预加载
- 级联删除
- GORM设计原理
应用程序
GORM
<--api操作接口-->
database / sql
<--连接接口/操作接口-->
数据库
-
SQL的生成
chain method:sql里的子句 finisher method:操作类型
-
SQL这样生成的原因
- 自定义Clause Builder
- 不同数据库甚至不同版本的数据库支持的SQL不同
- 根据自己数据库的版本对参数进行初始化,生成不同的SQL,自定义子句builder
- 扩展子句
- 扩展select子句后
- 扩展from子句后
- 自由扩展子句前中后
- 选择子句
- 不同的数据库(如PostgreSQL、MySQL、Clickhouse等)的sql操作有差异。
- 可以隐藏掉差异,在不改变代码的时候灵活去扩展、支持各种数据库。(即自定义它所支持的数据库子句类型,在不改变代码的情况下兼容不同的数据库)
- 自定义Clause Builder
-
插件是怎么工作的
finisher method -> 决定statement类型 -> 执行callbacks -> 生成SQL并执行
callbacks类型:create query update delete row raw -
插件这样工作的原因 - 灵活定制、自由扩展
- 多租户 (在每个操作后加上一个自定义的过滤方法,防止操作事故)
- 多数据库、读写分离(主数据库-写,从数据库-读;可以同时设置多组读写数据库,指定某一组的读/写数据库读取内容)
-
ConnPool
根据内容判断执行的是读/写数据库,来完成当前的请求
- 预编译,只需要做一次解析,加快执行速度
- 全局模式,所有DB操作都会预编译并缓存(缓存不含参数部分)
- 会话模式,后续会话的操作都会预编译并缓存(只针对当前会话)
- 流程
- 查找缓存的预编译SQL
- 未找到,将收到的SQL和Vars预编译
- 使用缓存的预编译SQL执行
- 通过一行配置迅速提升软件性能
interpolateParams=false它的预编译用完就扔掉,跟前面的预编译缓存不一样
- GORM最佳实践
- 数据序列化与SQL表达式
- 批量数据操作
- 代码复用、分库分表、Sharding
- 混沌工程
- Logger / Trace
- Migrator
- Gen代码生成 / Raw SQL
- 安全