fix issue: database connection pool does not work expectly

This commit is contained in:
John
2018-12-12 20:01:10 +08:00
parent 670993f769
commit 105a821069
6 changed files with 85 additions and 41 deletions

View File

@ -91,7 +91,7 @@ type Db struct {
charr string // SQL安全符号(右)
debug *gtype.Bool // (默认关闭)是否开启调试模式,当开启时会启用一些调试特性
sqls *gring.Ring // (debug=true时有效)已执行的SQL列表
cache *gcache.Cache // 查询缓存需要注意的是,事务查询不支持缓存
cache *gcache.Cache // 数据库缓存,包括底层连接池对象缓存及查询缓存需要注意的是,事务查询不支持查询缓存
maxIdleConnCount *gtype.Int // 连接池最大限制的连接数
maxOpenConnCount *gtype.Int // 连接池最大打开的连接数
maxConnLifetime *gtype.Int // (单位秒)连接对象可重复使用的时间长度
@ -248,40 +248,51 @@ func getLinkByType(dbType string) (Link, error) {
}
// 获得底层数据库链接对象
func (db *Db) getSqlDb(master bool) (*sql.DB, error) {
func (db *Db) getSqlDb(master bool) (sqlDb *sql.DB, err error) {
// 负载均衡
node, err := getConfigNodeByGroup(db.group, master)
if err != nil {
return nil, err
}
// 类型对象
link, err := getLinkByType(node.Type)
if err != nil {
return nil, err
}
sqlDb, err := link.Open(node)
if err != nil {
return nil, err
}
if node.MaxIdleConnCount > 0 {
sqlDb.SetMaxIdleConns(node.MaxIdleConnCount)
}
if n := db.maxIdleConnCount.Val(); n > 0 {
sqlDb.SetMaxIdleConns(n)
// 检查缓存连接池对象
cacheKey := node.String()
if v := db.cache.Get(cacheKey); v != nil {
return v.(*sql.DB), nil
}
v := db.cache.GetOrSetFuncLock(node.String(), func() interface{} {
sqlDb, err = link.Open(node)
if err != nil {
return nil
}
if node.MaxOpenConnCount > 0 {
sqlDb.SetMaxOpenConns(node.MaxOpenConnCount)
}
if n := db.maxOpenConnCount.Val(); n > 0 {
sqlDb.SetMaxOpenConns(n)
}
if n := db.maxIdleConnCount.Val(); n > 0 {
sqlDb.SetMaxIdleConns(n)
} else if node.MaxIdleConnCount > 0 {
sqlDb.SetMaxIdleConns(node.MaxIdleConnCount)
}
if node.MaxConnLifetime > 0 {
sqlDb.SetConnMaxLifetime(time.Duration(node.MaxConnLifetime) * time.Second)
if n := db.maxOpenConnCount.Val(); n > 0 {
sqlDb.SetMaxOpenConns(n)
} else if node.MaxOpenConnCount > 0 {
sqlDb.SetMaxOpenConns(node.MaxOpenConnCount)
}
if n := db.maxConnLifetime.Val(); n > 0 {
sqlDb.SetConnMaxLifetime(time.Duration(n) * time.Second)
} else if node.MaxConnLifetime > 0 {
sqlDb.SetConnMaxLifetime(time.Duration(node.MaxConnLifetime) * time.Second)
}
return sqlDb
}, 0)
if v != nil && sqlDb == nil {
sqlDb = v.(*sql.DB)
}
if n := db.maxConnLifetime.Val(); n > 0 {
sqlDb.SetConnMaxLifetime(time.Duration(n) * time.Second)
}
return sqlDb, nil
return
}
// 创建底层数据库master链接对象

View File

@ -89,7 +89,6 @@ func (db *Db) Query(query string, args ...interface{}) (*sql.Rows, error) {
if err != nil {
return nil,err
}
defer slave.Close()
p := db.link.handleSqlBeforeExec(&query)
if db.debug.Val() {
militime1 := gtime.Millisecond()
@ -125,7 +124,6 @@ func (db *Db) Exec(query string, args ...interface{}) (sql.Result, error) {
if err != nil {
return nil,err
}
defer master.Close()
p := db.link.handleSqlBeforeExec(&query)
if db.debug.Val() {
militime1 := gtime.Millisecond()
@ -259,12 +257,10 @@ func (db *Db) Select(tables, fields string, condition interface{}, groupBy, orde
}
// sql预处理执行完成后调用返回值sql.Stmt.Exec完成sql操作
// 记得调用sql.Stmt.Close关闭操作对象
func (db *Db) Prepare(query string) (*sql.Stmt, error) {
if master, err := db.Master(); err != nil {
return nil, err
} else {
defer master.Close()
return master.Prepare(query)
}
}
@ -274,7 +270,6 @@ func (db *Db) PingMaster() error {
if master, err := db.Master(); err != nil {
return err
} else {
defer master.Close()
return master.Ping()
}
}
@ -284,7 +279,6 @@ func (db *Db) PingSlave() error {
if slave, err := db.Slave(); err != nil {
return err
} else {
defer slave.Close()
return slave.Ping()
}
}

View File

@ -8,6 +8,7 @@
package gdb
import (
"fmt"
"sync"
)
@ -134,4 +135,15 @@ func (db *Db) SetMaxOpenConns(n int) {
// 如果 d <= 0 表示该链接会一直重复利用
func (db *Db) SetConnMaxLifetime(n int) {
db.maxConnLifetime.Set(n)
}
// 节点配置转换为字符串
func (node *ConfigNode) String() string {
if node.Linkinfo != "" {
return node.Linkinfo
}
return fmt.Sprintf(`%s@%s:%s,%s,%s,%s,%s,%d-%d-%d`, node.User, node.Host, node.Port,
node.Name, node.Type, node.Role, node.Charset,
node.MaxIdleConnCount, node.MaxOpenConnCount, node.MaxConnLifetime,
)
}

View File

@ -27,16 +27,12 @@ type Tx struct {
// 事务操作,提交
func (tx *Tx) Commit() error {
err := tx.tx.Commit()
tx.master.Close()
return err
return tx.tx.Commit()
}
// 事务操作,回滚
func (tx *Tx) Rollback() error {
err := tx.tx.Rollback()
tx.master.Close()
return err
return tx.tx.Rollback()
}
// (事务)数据库sql查询操作主要执行查询
@ -193,7 +189,6 @@ func (tx *Tx) Select(tables, fields string, condition interface{}, groupBy, orde
}
// sql预处理执行完成后调用返回值sql.Stmt.Exec完成sql操作
// 记得调用sql.Stmt.Close关闭操作对象
func (tx *Tx) Prepare(query string) (*sql.Stmt, error) {
return tx.tx.Prepare(query)
}

View File

@ -0,0 +1,36 @@
package main
import (
"gitee.com/johng/gf/g/database/gdb"
"time"
)
func main() {
gdb.AddDefaultConfigNode(gdb.ConfigNode {
Host : "127.0.0.1",
Port : "3306",
User : "root",
Pass : "12345678",
Name : "test",
Type : "mysql",
Role : "master",
Charset : "utf8",
MaxIdleConnCount : 10,
MaxOpenConnCount : 10,
MaxConnLifetime : 10,
})
db, err := gdb.New()
if err != nil {
panic(err)
}
// 开启调试模式以便于记录所有执行的SQL
db.SetDebug(true)
for {
for i := 0; i < 10; i++ {
go db.Table("user").All()
}
time.Sleep(time.Second)
}
}

View File

@ -1,9 +1,8 @@
package main
import (
"gitee.com/johng/gf/g/database/gdb"
"fmt"
"gitee.com/johng/gf/g/encoding/gparser"
"gitee.com/johng/gf/g/database/gdb"
)
func main() {
@ -27,8 +26,5 @@ func main() {
r, _ := db.Table("user").All()
if r != nil {
fmt.Println(r.ToList())
b, e := gparser.VarToJson(r.ToList())
fmt.Println(e)
fmt.Println(string(b))
}
}