diff --git a/g/database/gdb/gdb.go b/g/database/gdb/gdb.go index 8eec0cbdf..e66f23931 100644 --- a/g/database/gdb/gdb.go +++ b/g/database/gdb/gdb.go @@ -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链接对象 diff --git a/g/database/gdb/gdb_base.go b/g/database/gdb/gdb_base.go index 1cfc1b76b..ade922df1 100644 --- a/g/database/gdb/gdb_base.go +++ b/g/database/gdb/gdb_base.go @@ -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() } } diff --git a/g/database/gdb/gdb_config.go b/g/database/gdb/gdb_config.go index f3ed7df33..f3a6f490c 100644 --- a/g/database/gdb/gdb_config.go +++ b/g/database/gdb/gdb_config.go @@ -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, + ) } \ No newline at end of file diff --git a/g/database/gdb/gdb_transaction.go b/g/database/gdb/gdb_transaction.go index a65cffa87..692b3bb5b 100644 --- a/g/database/gdb/gdb_transaction.go +++ b/g/database/gdb/gdb_transaction.go @@ -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) } diff --git a/geg/database/orm/mysql/gdb_pool.go b/geg/database/orm/mysql/gdb_pool.go new file mode 100644 index 000000000..8f4c7dabf --- /dev/null +++ b/geg/database/orm/mysql/gdb_pool.go @@ -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) + } + +} \ No newline at end of file diff --git a/geg/database/orm/mysql/gdb_value.go b/geg/database/orm/mysql/gdb_value.go index ad9a2ba1a..7851f6dd6 100644 --- a/geg/database/orm/mysql/gdb_value.go +++ b/geg/database/orm/mysql/gdb_value.go @@ -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)) } } \ No newline at end of file