• 关于Golang中database/sql包的学习


    go-sql-driver

    请求一个连接的函数有好几种,执行完毕处理连接的方式稍有差别,大致如下:

    • db.Ping() 调用完毕后会马上把连接返回给连接池。

    • db.Exec() 调用完毕后会马上把连接返回给连接池,但是它返回的Result对象还保留这连接的引用,当后面的代码需要处理结果集的时候连接将会被重用。

    • db.Query() 调用完毕后会将连接传递给sql.Rows类型,当然后者迭代完毕或者显示的调用.Clonse()方法后,连接将会被释放回到连接池。

    • db.QueryRow()调用完毕后会将连接传递给sql.Row类型,当.Scan()方法调用之后把连接释放回到连接池。

    • db.Begin() 调用完毕后将连接传递给sql.Tx类型对象,当.Commit()或.Rollback()方法调用后释放连接。

      连接DB

      sql.Open的第一个参数是driver名称,第二个参数是driver连接数据库的信息,各个driver可能不同。DB不是连接,并且只有当需要使用时才会创建连接,如果想立即验证连接,需要用Ping()方法,如下:

      err = db.Ping()if err != nil {
          // do something here
      }

      sql.DB的设计就是用来作为长连接使用的。不要频繁Open, Close。比较好的做法是,为每个不同的datastore建一个DB对象,保持这些对象Open。如果需要短连接,那么把DB作为参数传入function,而不要在function中Open, Close。

      读取DB

      如果方法包含Query,那么这个方法是用于查询并返回rows的。其他情况应该用Exec()

      var (
          id int
          name string
      )
      rows, err := db.Query("select id, name from users where id = ?", 1)if err != nil {
          log.Fatal(err)
      }
      defer rows.Close()for rows.Next() {
          err := rows.Scan(&id, &name)
          if err != nil {
              log.Fatal(err)
          }
          log.Println(id, name)
      }
      err = rows.Err()if err != nil {
          log.Fatal(err)
      }

      上面代码的过程为:db.Query()表示向数据库发送一个query,defer rows.Close()非常重要,遍历rows使用rows.Next(), 把遍历到的数据存入变量使用rows.Scan(), 遍历完成后检查error。有几点需要注意:

      1. 检查遍历是否有error

      2. 结果集(rows)未关闭前,底层的连接处于繁忙状态。当遍历读到最后一条记录时,会发生一个内部EOF错误,自动调用rows.Close(),但是如果提前退出循环,rows不会关闭,连接不会回到连接池中,连接也不会关闭。所以手动关闭非常重要。rows.Close()可以多次调用,是无害操作。

      单行Query

      err在Scan后才产生,所以可以如下写:

      var name stringerr = db.QueryRow("select name from users where id = ?", 1).Scan(&name)if err != nil {
          log.Fatal(err)
      }
      fmt.Println(name)

      修改数据,事务

      一般用Prepare()和Exec()完成INSERTUPDATEDELETE操作。

      事务

      db.Begin()开始事务,Commit() 或 Rollback()关闭事务。Tx从连接池中取出一个连接,在关闭之前都是使用这个连接。Tx不能和DB层的BEGINCOMMIT混合使用。

      如果你需要通过多条语句修改连接状态,你必须使用Tx,例如:

      • 创建仅对单个连接可见的临时表

      • 设置变量,例如SET @var := somevalue

      • 改变连接选项,例如字符集,超时

      处理Error

      循环Rows的Error

      如果循环中发生错误会自动运行rows.Close(),用rows.Err()接收这个错误,Close方法可以多次调用。循环之后判断error是非常必要的。

      关闭Resultsets时的error

      如果你在rows遍历结束之前退出循环,必须手动关闭

    关于连接池

    1. 当需要连接,且连接池中没有可用连接时,新的连接就会被创建。

    2. 默认没有连接上限,这可能会导致数据库产生错误“too many connections”

    3. db.SetMaxIdleConns(N)设置最大空闲连接数

    4. db.SetMaxOpenConns(N)设置最大打开连接数

    5. 长时间保持空闲连接可能会导致db timeout

  • 相关阅读:
    动手学习TCP:TCP连接建立与终止
    动手学习TCP: 环境搭建
    Python 数据分析4
    Django unittest 单元测试
    Django commands自定制
    Python mac安装mysqlclient的一个bug
    Centos7 开机启动流程
    Centos 06 文件类型和扩展名&索引节点inode和存储块block
    Centos 05 系统目录讲解
    Linux 踩过的坑系列-01
  • 原文地址:https://www.cnblogs.com/DaBing0806/p/6680759.html
Copyright © 2020-2023  润新知