关于Golang中database/sql包的学习

go-sql-driversql

请求一个链接的函数有好几种,执行完毕处理链接的方式稍有差异,大体以下:数据库

  • db.Ping() 调用完毕后会立刻把链接返回给链接池。函数

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

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

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

  • 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()string

    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。有几点须要注意:it

    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

相关文章
相关标签/搜索