關於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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM