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

回滾事務。

相關文章
相關標籤/搜索