【课程笔记】设计模式之 Database/SQL 与 Gorm实践 | 青训营笔记

156 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记。

1、理解 Database/SQL

1.1、基本用法-Quick Start

database sql包只是实现一个统一的接口,不同的数据库与自己去实现它们自己的driver
//import mysql的driver,实现了怎么去连接数据库,解析数据库等等
import XXX/go-sql-driver/mysql 
//利用driver + DSN(data source name)初始化DB连接
db, err := sql.Open("mysql",DSN)
//rows是一个游标?可以通过.Next()获取下一条数据
rows, err := db.Query(XXX,X)
//处理完返回的数据后,记得将rows.Close(),避免资源泄露
defer rows.Close()
//除了数据相关的错,都会通过这个err返回
if rows.Err() != nil {
}

1.2 、database sql包设计原理

image-20220514221605947.png

  • databse/sql 为应用程序提供标准的API操作接口,为下层驱动提供一些接口,内部实现一些对连接池的管理(一种池化技术,应对请求量特别大的情况,将一些昂贵的资源放到一个特定的池子里)
  • database sql有利于支持各种各样的数据库,修改连接接口即可
  • 对连接池管理
    • 连接池配置:

      • 取出连接池状态:image-20220514223157314.png
      • 操作过程的伪实现:image-20220514223325939.png
    • drivers实现的连接接口image-20220514223831406.png

      • 使用driver:image-20220514224012066.png
        • 2017年go提出了一个新的接口,可以使用结构体:image-20220514230427612.png
          • 使用:image-20220514230455708.png
    • 操作接口

      • DB连接的几种连接:
        • 直接连接/Conn:直接通过tcp链接访问数据库;
        • 预编译/Stmt:执行同样的sql,后续仅根据reference id访问数据库,减少网络传输和sqwl解析时间;
        • 事务/Tx
      • 处理返回数据的几种方式:
        • Exec / ExecContext -> Result:成功失败的信息
        • Query / QueryContext ->Rows(Columns):以行的形式返回结果
        • QueryRow / QueryRowContext ->Row(Rows 简化):只会读取一行数据

02GORM使用简介

2.1基本定义

GROM: 设计简介、功能强大、自由扩展的全功能ORM(Object Relational Mapping)

image-20220514234712181.png

2.2 CRUD基本用法

  • 2种方法是等价的,取值放到users中:

    • image-20220514234857029.png
    • image-20220515230549768.png
    • 通过使用gorm,避免引入了driver,避免忘记rows.close(),err检查也简单更多了
  • 基本用法--CRUD(create && update)

    • image-20220515231024544.png
    • image-20220515231038770.png

2.3 模型定义

  • 举例,2种模型定义的方式等价:
    • image-20220515231110683.png
    • image-20220515231400533.png

2.3模型定义-惯例约定

image-20220515231729037.png

2.4关联介绍

image-20220515231829414.png

2.4 关联操作-CRUD

image-20220515232020501.png

2.4 关联操作-Preload / Joins预加载

image-20220515232516533.png

2.4 关联操作-级联删除

保障没有一些孤儿的数据

image-20220515233240612.png

  • 方法1:使用数据库约束自动删除
  • 方法2:使用Select

03 GORM设计原理

image-20220515233526643.png

  • 在databse/sql包前封装了一层

3.1 SQL是怎么生成的

  • image-20220515233810961.png

    • 一条普通的查询sql,sql statement
  • image-20220515234233174.png

    • grom statement
  • chain method的内部实现:image-20220515234619019.png

  • Finisher method的内部实现:image-20220515234941983.png

  • 为什么这么设计呢?

    • 可以自定义Clause Builder(子句生成的sql)
      • 方便使用同一套逻辑实现不同的数据库操作,举例:image-20220515235444710.png
    • 方便扩展Clause(子句)
      • 举例:image-20220516000104630.png
      • grom可以通过自由选择子句的方式,生成不同的sql,因为不同的数据库支持的sql语句不一样,例如:image-20220516000605790.png

3.2插件是怎么工作的

image-20220516000911687.png

  • create callbacks:image-20220516002606150.png

    • 使用db.Create()的时候,把插件系统内定义的所有create相关的注册的callbacks,均取出来调用
    • 除此之外,插件还提供了自定义callbacks的功能:image-20220516002959160.png
  • 为什么这么设计呢?

    • 灵活定制,自由扩展
      • 支持多租户:image-20220516003601524.png
      • 支持多数据库、读写分离:image-20220516003839500.png
      • 支持加解密、混沌工程

3.3 ConnPool是什么

image-20220516004043543.png

image-20220516004343201.png

  • 可以缓存以前的编译结果
    • 全局模式,所有DB操作都会预编译并缓存(缓存不包含参数)
    • 会话模式:后续会话的操作都会预编译并缓存
  • 如何通过一行代码提升性能:
    • mysql driver提供了一个参数interpolateParams(默认false: 执行、调用和关闭预编译sql),false可节省大量时间。

3.4 Dialector是什么

  • 橙色部分(定义了怎么去连接数据库):image-20220516005804223.png
  • image-20220516010024657.png

04 GORM最佳实践

4.1 数据序列化与SQL表达式-sql表达式更新创建

image-20220516010317589.png

4.1 数据序列化与SQL表达式-sql表达式查询

image-20220516010544677.png

4.1 数据序列化与SQL表达式-sql数据序列化

4.2 批量数据操作-批量创建/查询

image-20220516010709689.png

  • 避免一次性将所有数据放入内存

4.2 批量数据操作-批量更新

image-20220516011149577.png

4.2 批量数据操作-批量数据加速操作

  • 方法1:关闭默认事务
  • 方法2:默认批量导入会调用Hooks方法,使用‘SkipHooks'跳过
  • 方法3:使用Prepared Statement
  • 混合使用

4.3代码复用、分库分表、Sharding-代码复用

  • 代码复用:image-20220516011502818.png

  • 分库分表:image-20220516011545778.png

  • Sharding:image-20220516011624940.png

4.4混沌工程 / 压测

  • 插件:sqlchaos

image-20220516011820649.png

  • 压测:image-20220516011933264.png

4.5 Logger / Trace

image-20220516012037665.png

4.6数据库迁移管理

image-20220516012151380.png

image-20220516012255376.png

image-20220516012324499.png

4.7 Gen代码生成 / raw sql

image-20220516012455588.png

4.7 Gen代码生成 / Gen

image-20220516012650638.png

4.8 安全问题

image-20220516012843972.png