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
}

浙公网安备 33010602011771号