Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
二次元的罪恶王冠
beego
提交
526a5463
B
beego
项目概览
二次元的罪恶王冠
/
beego
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
B
beego
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
526a5463
编写于
6月 23, 2020
作者:
M
Ming Deng
提交者:
GitHub
6月 23, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #4025 from jianzhiyao/develop
Fix: Too Many Prepare Statement
上级
f5c580a4
a28d294a
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
73 addition
and
22 deletion
+73
-22
orm/db_alias.go
orm/db_alias.go
+70
-19
orm/orm.go
orm/orm.go
+3
-3
未找到文件。
orm/db_alias.go
浏览文件 @
526a5463
...
...
@@ -18,6 +18,7 @@ import (
"context"
"database/sql"
"fmt"
lru
"github.com/hashicorp/golang-lru"
"reflect"
"sync"
"time"
...
...
@@ -106,8 +107,8 @@ func (ac *_dbCache) getDefault() (al *alias) {
type
DB
struct
{
*
sync
.
RWMutex
DB
*
sql
.
DB
stmt
s
map
[
string
]
*
sql
.
Stmt
DB
*
sql
.
DB
stmt
Decorators
*
lru
.
Cache
}
func
(
d
*
DB
)
Begin
()
(
*
sql
.
Tx
,
error
)
{
...
...
@@ -118,19 +119,20 @@ func (d *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
return
d
.
DB
.
BeginTx
(
ctx
,
opts
)
}
func
(
d
*
DB
)
getStmt
(
query
string
)
(
*
sql
.
Stmt
,
error
)
{
//su must call release to release *sql.Stmt after using
func
(
d
*
DB
)
getStmtDecorator
(
query
string
)
(
*
stmtDecorator
,
error
)
{
d
.
RLock
()
c
,
ok
:=
d
.
stmt
s
[
query
]
c
,
ok
:=
d
.
stmt
Decorators
.
Get
(
query
)
d
.
RUnlock
()
if
ok
{
return
c
,
nil
return
c
.
(
*
stmtDecorator
)
,
nil
}
d
.
Lock
()
c
,
ok
=
d
.
stmt
s
[
query
]
c
,
ok
=
d
.
stmt
Decorators
.
Get
(
query
)
if
ok
{
d
.
Unlock
()
return
c
,
nil
return
c
.
(
*
stmtDecorator
)
,
nil
}
stmt
,
err
:=
d
.
Prepare
(
query
)
...
...
@@ -138,9 +140,11 @@ func (d *DB) getStmt(query string) (*sql.Stmt, error) {
d
.
Unlock
()
return
nil
,
err
}
d
.
stmts
[
query
]
=
stmt
sd
:=
newStmtDecorator
(
stmt
)
d
.
stmtDecorators
.
Add
(
query
,
sd
)
d
.
Unlock
()
return
stmt
,
nil
return
sd
,
nil
}
func
(
d
*
DB
)
Prepare
(
query
string
)
(
*
sql
.
Stmt
,
error
)
{
...
...
@@ -152,52 +156,63 @@ func (d *DB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error
}
func
(
d
*
DB
)
Exec
(
query
string
,
args
...
interface
{})
(
sql
.
Result
,
error
)
{
s
tmt
,
err
:=
d
.
getStmt
(
query
)
s
d
,
err
:=
d
.
getStmtDecorator
(
query
)
if
err
!=
nil
{
return
nil
,
err
}
stmt
:=
sd
.
acquire
()
defer
sd
.
release
()
return
stmt
.
Exec
(
args
...
)
}
func
(
d
*
DB
)
ExecContext
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
(
sql
.
Result
,
error
)
{
s
tmt
,
err
:=
d
.
getStmt
(
query
)
s
d
,
err
:=
d
.
getStmtDecorator
(
query
)
if
err
!=
nil
{
return
nil
,
err
}
stmt
:=
sd
.
acquire
()
defer
sd
.
release
()
return
stmt
.
ExecContext
(
ctx
,
args
...
)
}
func
(
d
*
DB
)
Query
(
query
string
,
args
...
interface
{})
(
*
sql
.
Rows
,
error
)
{
s
tmt
,
err
:=
d
.
getStmt
(
query
)
s
d
,
err
:=
d
.
getStmtDecorator
(
query
)
if
err
!=
nil
{
return
nil
,
err
}
stmt
:=
sd
.
acquire
()
defer
sd
.
release
()
return
stmt
.
Query
(
args
...
)
}
func
(
d
*
DB
)
QueryContext
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
(
*
sql
.
Rows
,
error
)
{
s
tmt
,
err
:=
d
.
getStmt
(
query
)
s
d
,
err
:=
d
.
getStmtDecorator
(
query
)
if
err
!=
nil
{
return
nil
,
err
}
stmt
:=
sd
.
acquire
()
defer
sd
.
release
()
return
stmt
.
QueryContext
(
ctx
,
args
...
)
}
func
(
d
*
DB
)
QueryRow
(
query
string
,
args
...
interface
{})
*
sql
.
Row
{
s
tmt
,
err
:=
d
.
getStmt
(
query
)
s
d
,
err
:=
d
.
getStmtDecorator
(
query
)
if
err
!=
nil
{
panic
(
err
)
}
stmt
:=
sd
.
acquire
()
defer
sd
.
release
()
return
stmt
.
QueryRow
(
args
...
)
}
func
(
d
*
DB
)
QueryRowContext
(
ctx
context
.
Context
,
query
string
,
args
...
interface
{})
*
sql
.
Row
{
stmt
,
err
:=
d
.
getStmt
(
query
)
sd
,
err
:=
d
.
getStmtDecorator
(
query
)
if
err
!=
nil
{
panic
(
err
)
}
stmt
:=
sd
.
acquire
()
defer
sd
.
release
()
return
stmt
.
QueryRowContext
(
ctx
,
args
)
}
...
...
@@ -275,9 +290,9 @@ func addAliasWthDB(aliasName, driverName string, db *sql.DB) (*alias, error) {
al
.
Name
=
aliasName
al
.
DriverName
=
driverName
al
.
DB
=
&
DB
{
RWMutex
:
new
(
sync
.
RWMutex
),
DB
:
db
,
stmt
s
:
make
(
map
[
string
]
*
sql
.
Stmt
),
RWMutex
:
new
(
sync
.
RWMutex
),
DB
:
db
,
stmt
Decorators
:
newStmtDecoratorLruWithEvict
(
),
}
if
dr
,
ok
:=
drivers
[
driverName
];
ok
{
...
...
@@ -403,3 +418,39 @@ func GetDB(aliasNames ...string) (*sql.DB, error) {
}
return
nil
,
fmt
.
Errorf
(
"DataBase of alias name `%s` not found"
,
name
)
}
type
stmtDecorator
struct
{
wg
sync
.
WaitGroup
lastUse
int64
stmt
*
sql
.
Stmt
}
func
(
s
*
stmtDecorator
)
acquire
()
*
sql
.
Stmt
{
s
.
wg
.
Add
(
1
)
s
.
lastUse
=
time
.
Now
()
.
Unix
()
return
s
.
stmt
}
func
(
s
*
stmtDecorator
)
release
()
{
s
.
wg
.
Done
()
}
//garbage recycle for stmt
func
(
s
*
stmtDecorator
)
destroy
()
{
s
.
wg
.
Wait
()
_
=
s
.
stmt
.
Close
()
}
func
newStmtDecorator
(
sqlStmt
*
sql
.
Stmt
)
*
stmtDecorator
{
return
&
stmtDecorator
{
stmt
:
sqlStmt
,
lastUse
:
time
.
Now
()
.
Unix
(),
}
}
func
newStmtDecoratorLruWithEvict
()
*
lru
.
Cache
{
cache
,
_
:=
lru
.
NewWithEvict
(
1000
,
func
(
key
interface
{},
value
interface
{})
{
value
.
(
*
stmtDecorator
)
.
destroy
()
})
return
cache
}
orm/orm.go
浏览文件 @
526a5463
...
...
@@ -559,9 +559,9 @@ func NewOrmWithDB(driverName, aliasName string, db *sql.DB) (Ormer, error) {
al
.
Name
=
aliasName
al
.
DriverName
=
driverName
al
.
DB
=
&
DB
{
RWMutex
:
new
(
sync
.
RWMutex
),
DB
:
db
,
stmt
s
:
make
(
map
[
string
]
*
sql
.
Stmt
),
RWMutex
:
new
(
sync
.
RWMutex
),
DB
:
db
,
stmt
Decorators
:
newStmtDecoratorLruWithEvict
(
),
}
detectTZ
(
al
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录