Golang中database/sql包

驱动mysql

github.com/go-sql-driver/mysql

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

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

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

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

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

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

    链接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()ui

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

    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

 

补充:

二、数据库

2.一、type DB struct{}

DB是一个数据库句柄,表明一个具备零到多个底层链接的链接池。

它能够安全的被多个go程同时使用。

链接池的大小能够用SetMaxIdleConns方法控制。

2.二、经常使用方法

(1)func Open(driverName, dataSourceName string) (*DB, error)

打开数据库,返回数据库句柄,DB能够安全的被多个go程同时使用,并会维护自身的闲置链接池。

Open函数只需调用一次,不多须要关闭DB。

(2)func (db *DB) Driver() driver.Driver

返回数据库下层驱动。

(3)func (db *DB) Ping() error

检查与数据库的链接是否仍有效,若是须要会建立链接。

(4)func (db *DB) Close() error

关闭数据库,释听任何打开的资源。

通常不会关闭DB,由于DB句柄一般被多个go程共享,并长期活跃。

(5)func (db *DB) SetMaxOpenConns(n int)

设置与数据库创建链接的最大数目。

若是n大于0且小于最大闲置链接数,会将最大闲置链接数减少到匹配最大开启链接数的限制。

若是n <= 0,不会限制最大开启链接数,默认为0(无限制)。

(6)func (db *DB) SetMaxIdleConns(n int)

设置链接池中的最大闲置链接数。

若是n大于最大开启链接数,则新的最大闲置链接数会减少到匹配最大开启链接数的限制。

若是n <= 0,不会保留闲置链接。

(7)func (db *DB) Exec(query string, args ...interface{}) (Result, error)

执行一次命令(包括查询、删除、更新、插入等),不返回任何执行结果。

参数args表示query中的占位参数。

(8)func (db *DB) Query(query string, args ...interface{}) (*Rows, error)

执行一次查询,返回多行结果(即Rows),通常用于执行select命令。

(9)func (db *DB) QueryRow(query string, args ...interface{}) *Row

执行一次查询,并指望返回最多一行结果(即Row)。

老是返回非nil的值,直到返回值的Scan方法被调用时,才会返回被延迟的错误。

(10)func (db *DB) Prepare(query string) (*Stmt, error)

建立一个准备好的状态用于以后的查询和命令。

返回值能够同时执行多个查询和命令。

(11)func (db *DB) Begin() (*Tx, error)

开始一个事务。

隔离水平由数据库驱动决定。

三、数据表

3.一、type Rows{}

Rows是查询的结果。

它的游标指向结果集的第零行,使用Next方法来遍历各行结果。

3.二、经常使用方法

(1)func (rs *Rows) Columns() ([]string, error)

返回列名。

若是Rows已经关闭会返回错误。

(2)func (rs *Rows) Scan(dest ...interface{}) error

Scan将当前行各列结果填充进dest指定的各个值中。

若是某个参数的类型为*[]byte,Scan会保存对应数据的拷贝,该拷贝为调用者全部,能够安全的,修改或无限期的保存。

若是参数类型为*RawBytes能够避免拷贝;参见RawBytes的文档获取其使用的约束。

若是某个参数的类型为*interface{},Scan会不作转换的拷贝底层驱动提供的值。

若是值的类型为[]byte,会进行数据的拷贝,调用者能够安全使用该值。

(3)func (rs *Rows) Next() bool

Next准备用于Scan方法的下一行结果。

若是成功会返回真,若是没有下一行或者出现错误会返回假。

每一次调用Scan方法,甚至包括第一次调用该方法,都必须在前面先调用Next方法。

(4)func (rs *Rows) Close() error

关闭Rows,阻止对其更多的列举。

若是Next方法返回假,Rows会自动关闭。

检查Err方法结果的条件。

Close方法是幂等的(屡次调用无效的成功),不影响Err方法的结果。

(5)func (rs *Rows) Err() error

Err返回可能的、在迭代时出现的错误。

Err需在显式或隐式调用Close方法后调用。

四、数据行

4.一、type Row{}

QueryRow方法返回Row,表明单行查询结果。

4.二、经常使用方法

(1)func (r *Row) Scan(dest ...interface{}) error

Scan将该行查询结果各列分别保存进dest参数指定的值中。

若是该查询匹配多行,Scan会使用第一行结果并丢弃其他各行。

若是没有匹配查询的行,Scan会返回ErrNoRows。

五、SQL命令状态

5.一、type Stmt struct{}

Stmt是准备好的状态。

Stmt能够安全的被多个go程同时使用。

5.二、经常使用方法

(1)func (s *Stmt) Exec(args ...interface{}) (Result, error)

使用提供的参数执行准备好的命令状态,返回Result类型的该状态执行结果的总结。

(2)func (s *Stmt) Query(args ...interface{}) (*Rows, error)

使用提供的参数执行准备好的查询状态,返回Rows类型查询结果。

(3)func (s *Stmt) QueryRow(args ...interface{}) *Row

使用提供的参数执行准备好的查询状态。

若是在执行时遇到了错误,该错误会被延迟,直到返回值的Scan方法被调用时才释放。

返回值老是非nil的。

若是没有查询到结果,*Row类型返回值的Scan方法会返回ErrNoRows;不然,Scan方法会扫描结果第一行并丢弃其他行。

(4)func (s *Stmt) Close() error

关闭状态。

六、事务

6.一、type Tx struct{}

Tx表明一个进行中的数据库事务。

一次事务必须以对Commit或Rollback的调用结束。

调用Commit或Rollback后,全部对事务的操做都会失败并返回错误值ErrTxDone。

6.二、经常使用方法

(1)func (tx *Tx) Exec(query string, args ...interface{}) (Result, error)

执行命令,但不返回结果。例如执行insert和update。

(2)func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error)

执行查询并返回零到多行结果(Rows),通常执行select命令。

(3)func (tx *Tx) QueryRow(query string, args ...interface{}) *Row

执行查询并指望返回最多一行结果(Row)。

老是返回非nil的结果,查询失败的错误会延迟到在调用该结果的Scan方法时释放。

(4)func (tx *Tx) Prepare(query string) (*Stmt, error)

准备一个专用于该事务的状态。

返回的该事务专属状态操做在Tx递交会回滚后不能再使用。

(5)func (tx *Tx) Stmt(stmt *Stmt) *Stmt

使用已存在的状态生成一个该事务特定的状态。

(6)func (tx *Tx) Commit() error

提交事务。

(7)func (tx *Tx) Rollback() error

回滚事务。

相关文章
相关标签/搜索