go 自己封的postgresql連接池操作包


    測並發時由於使用db時沒有lock,當連接數超過postgres設定的最大值時報錯too many clients,於是問了下老師,老師說用連接池,一開始打開固定個數的db,每次都用這些db,而且每個db用的時候要加鎖

    於是就開始想如何用lock來實現每次讓進來的數據庫請求排隊,每次分配一個空閑的db給隊列中第一個請求,但想了好久發現用鎖處理起來好復雜,無法確定哪些db是空閑的,又改如何讓請求排隊

    后來實在想不出來,換了個思路,能不能用go的特性channal實現,猛然發現可以一開始將固定個數的db塞到channal,每次請求出隊一個可用的db,用完后又將db返回channal,而且channal自帶鎖的功能,當channal為空時(沒有db可用)請求會等待,形成了自然隊列,前面的所有問題都解決了

package myDB

import (
    "database/sql"
    "errors"

    _ "github.com/lib/pq"
)

//var db *sql.DB = nil
//
//func OpenSql() error {
//  var err error = nil
//  db, err = sql.Open("postgres", "port=5432 user=postgres password=123456 dbname=postgres sslmode=disable")
//  return err
//}
//
//func GetDB() (*sql.DB, error) {
//  if db == nil {
//      return nil, errors.New("db hadn't open")
//  }
//  return db, nil
//}

var dbQueue chan *sql.DB

func Init(queue chan *sql.DB) {
    dbQueue = queue
}
func open() *sql.DB {
    return <-dbQueue
}
func close(db *sql.DB) {
    dbQueue <- db
}

func dealResult(result sql.Result) error {
    affect, err := result.RowsAffected()
    if err != nil {
        return err
    }
    if affect <= 0 {
        return errors.New("DBExec no affect")
    }
    return nil
}
func ExecSql(Sql string, args ...interface{}) error {
    db := open()
    defer close(db)
    stmt, err := db.Prepare(Sql)
    if err != nil {
        return err
    }
    defer stmt.Close()
    result, err := stmt.Exec(args...)
    if err != nil {
        return err
    }
    return dealResult(result)
}

func QuerySql(Sql string, args ...interface{}) (*sql.Rows, error) {
    db := open()
    defer close(db)
    stmt, err := db.Prepare(Sql)
    if err != nil {
        return nil, err
    }
    defer stmt.Close()
    rows, err := stmt.Query(args...)
    if err != nil {
        return nil, err
    }
    return rows, err
}

func TxQuerySql(tx *sql.Tx, Sql string, args ...interface{}) (*sql.Stmt, *sql.Rows, error) {
    stmt, err := tx.Prepare(Sql)
    if err != nil {
        return nil, nil, err
    }
    rows, err := stmt.Query(args...)
    if err != nil {
        return nil, nil, err
    }
    return stmt, rows, err
}

func TxExecSql(tx *sql.Tx, Sql string, args ...interface{}) error {
    stmt, err := tx.Prepare(Sql)
    if err != nil {
        return err
    }
    defer stmt.Close()
    result, err := stmt.Exec(args...)
    if err != nil {
        return err
    }
    return dealResult(result)
}

func ExecMultiSql(Sql string, member []string, args ...interface{}) error {
    db := open()
    defer close(db)
    stmt, err := db.Prepare(Sql)
    if err != nil {
        return err
    }
    defer stmt.Close()
    for _, val := range member {
        allArgs := make([]interface{}, 0)
        allArgs = append(allArgs, val)
        allArgs = append(allArgs, args...)
        result, err := stmt.Exec(allArgs...)
        if err != nil {
            return err
        }
        err = dealResult(result)
        if err != nil {
            return err
        }
    }
    return nil
}

func TxExecMultiSql(tx *sql.Tx, Sql string, member []string, args ...interface{}) error {
    stmt, err := tx.Prepare(Sql)
    if err != nil {
        return err
    }
    defer stmt.Close()
    for _, val := range member {
        allArgs := make([]interface{}, 0)
        allArgs = append(allArgs, val)
        allArgs = append(allArgs, args...)
        result, err := stmt.Exec(allArgs...)
        if err != nil {
            return err
        }
        err = dealResult(result)
        if err != nil {
            return err
        }
    }
    return nil
}

  


免責聲明!

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



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