Database/SQL 与 GORM 实践 | 青训营笔记

156 阅读3分钟

database / sql 介绍

基本用法

  1. 导入driver,使用 driver+ DSN 初始化DB连接。
  2. 执行一条SQL,定义一个变量rows取回执行后返回的数据。处理完毕,需要释放链接。
  3. 通过游标遍历,对数据和错误进行处理。
  4. 遍历结束后不要忘记处理rows的错误。

设计原理

  • 应用程序->database/sql->数据库
  • database/sql采用集锦接口的设计原则,对上层的应用程序提供一个标准API的操作接口,对下层驱动暴露一些简单的驱动接口(连接接口、操作接口等),而自己内部实现连接池的管理。
  • 替换其他数据库只实现需要替换接口。
  • 连接池通过池化实现。
  • 连接池管理:连接池配置和连接池状态。
  • 操作过程的伪实现:
  1. 从连接池获取连接或通过driver新建连接
  2. 有空闲连接->reuse->max life time,没有则新建连接->max open...
  3. 将连接放回连接池
  4. validateConnection 有无错误 & max life time,max idle conns检查
  5. 连接实现driver.Queryer,driver.Execer等interface
  • Driver连接接口:通过Register(name,driver)注册driver
  • DB 连接的类型:
  1. 直接连接/Conn
  2. 预编译/Stmt
  3. 事务/Tx
  • 处理返回数据的方式:
  1. Exec/ExecContext->Result
  2. Query/QueryContext->Rows(Columns)
  3. QueryRow/QueryRowContext->Row(Rows的简化版)
  • Driver操作接口:通过drivers.Rows接口进行操作,Next(dest []value)解析数据

GORM 使用简介

设计简洁、功能强大、自由扩展的全功能ORM

基本用法

创建数据->导入数据库->读取->增删改查

模型定义

范式:约定优于配置。

关联介绍

  • o是object,r是relation。gorm提供很多支持,可以查看相关文档介绍。
  • 关联操作:Preload / Joins 预加载、级联删除

GORM 设计原理

应用程序->GORM->database/sql->数据库

SQL生成

  • SQL 语句:select from* where group by order by limit for*
  • GORM 语句:db.wWere("role <> ?","manager").Where("age > ?",35).Limit(100).Order("age desc").Find(&user)

插件工作流程

Finisher Method->决定Statement类型->执行Callbacks->生成SQL并执行(后面3种组成插件系统)

设计原因

灵活定制+自由扩展:多租户、多数据库且读写分离、加解密和混沌工程等。

ConnPool

  • 总体实现:GORM --SQL--> ConnPool(通过database / sql的数据包DB Conn实现接口) --连接池-->数据库
  • 具体流程:
  •          DB Conn(写DB)--连接池-->数据库
    
  •         (箭头)DML Statement
    
  • GORM--SQL--> ConnPool --事务--> DB Conn
  •         (箭头)DML Statement
    
  •          DB Conn(读DB)--连接池-->数据库   
    
  • 外部流程:
  •                               database / sql
    
  • 应用程序-> GORM --ConnPool插件--> API
  •                               Caches
    

Dialector

定制SQL生成、定制GORM插件、定制ConnPool、定制企业特性逻辑等。

GORM 最佳实践

数据序列化与SQL表达式

  • SQL表达式更新创建:
  1. 通过gorm.Expr使用SQL表达式
  2. 使用GORMValuer使用SQL表达式 /SubQuery
  3. 通过gorm.DB使用SubQuery
  • SQL表达式查询:
  1. 使用gorm.Expr
  2. Struct 定义 GormValuer
  3. 自定义查询SQL实现接口clause.Expression
  • 数据序列化:
  1. 自定义数据格式实现接口Scanner,Valuer
  2. 自定义数据格式实现Serializer接口

批量数据操作

  • 批量创建/查询:
  1. sql.Rows Scan
  2. gorm ScanRows
  • 批量更新:db.clauses(...)
  • 批量数据加速操作:
  1. 关闭默认事务
  2. 默认批量导入会调用Hooks方法,使用SkipHooks跳过
  3. 使用Prepared Statement

代码复用、分库分表、Sharding

  • 代码复用:db.Scopes(...)
  • 分库分表:+-操作
  • Sharding:sharding.Register(...)、sharding.Config(...)等

混沌工程/压测

人为制造测试机,保证数据一致性。

Logger/Trace

logger.New(...)等。

Migrator

  • 自动迁移数据库:db.AutoMigrate(...)

Gen 代码生成/Raw SQL

  • 可以通过db.Table(...).Select(...).Row(...)使用GORM API构建SQL

安全

  • 安全:以参数形式传入数据库执行语句
  • 不安全:通过SQL注入,直接拼接语句