理解Database/sql|青训营笔记13

197 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 13天。

前言

本文学习database/sql的基础语法,设计原理及基础概念

基础语法

实现import driver

import (
  "database/sqL"
  _"github com/go-sql-driver/mysql"
)

使用driver+DSN初始化DB连接,并执行一条SQL,通过rows取回返回的数据

处理完毕后,需要释放链接:

func main() {
  db, err := sql.Open("mysqL""user: password@tcp(127.0.0.1:3306)/hello")
  rows, err := db.Query("select id, name from users where id = ?", 1)
  if  err!=nil{
    // xxx
  }
 defer rows.Close()

数据、错误处理:

var users User
for rows.Next() {
  var user User
  err := rows.Scan(&user.ID, &user.Name)
  if err!=nil{
    // ...
  }

  users = append(users, user)
}

处理错误:

if rows.Err() != nil {
  // ...
}

设计原理

image.png
  • 连接池
image.png
  • 连接池配置
func (db *DB) SetConnMaxIdleTime(d time.Duration)
func (db *DB) SetConnMaxLifetime(d time.Duration)
func (db *DB) SetMaxIdleConns(n int)
func (db *DB) SetMaxOpenConns(n int)

  • 连接池状态
func(db *DB) Stats() DBStats

  • 操作过程伪实现
for i := 0; i < maxBadConnRetries; i++ { 
  //从连接池获取连接或通过driver新建连接
  dc, err := db. conn(ctx, strategy)
    //有空闲连接-> reuse -> max life time
    //新建连接-> max open... 
  
  //将连接放回连接池
  defer dc.db.putConn(dc, err,true)
    // validateConnection 有无错误
    // max life time, max idle conns 检查

  //连接实现driver . Queryer, driver, Execer 等interface
  if err == nil {
    err = dc.ci.Query(sql, args...)
  }

  isBadConn = errors.Is(err, driver.ErrBadConn)
  if !isBadConn {
    break
  }
}
  • Driver连接端口
//注册全局driver
func Register(name string, driver driver. Driver) {
    driversMu.Lock()
    defer driversMu.UnLock()
    if driver == nil {
        panic(" sqL: Register driver is nil") 
    }
    if _,dup := drivers[name]; dup {
        panic("sqL: Register called twice for driver” + name)
    }
    drivers[name] = driver
}
// Driver接口
type Driver interface {
    // Open returns a new connection to the database .
    Open(name string) (Conn, error)
}
  • DB连接的几种类型
    • 直接连接/ Conn
    • 预编译/ Stmt
    • 事务/ Tx
  • 处理返回数据的几种方式
    • Exec / ExecContext > Result
    • Query / QueryContext -> Rows (Columns)
    • QueryRow / QueryRowContext -> Row (Rows简化)

总结

Go使用SQL与类SQL数据库的惯例是通过标准库database/sql。这是一个对关系型数据库的通用抽象,它提供了标准的、轻量的、面向行的接口。不过database/sql的包文档只讲它做了什么,却对如何使用只字未提。快速指南远比堆砌事实有用,本文讲述了database/sql的使用方法及其注意事项。

Go使用SQL与类SQL数据库的惯例是通过标准库database/sql。这是一个对关系型数据库的通用抽象,它提供了标准的、轻量的、面向行的接口。不过database/sql的包文档只讲它做了什么,却对如何使用只字未提。快速指南远比堆砌事实有用,本文讲述了database/sql的使用方法及其注意事项。