Hi 大家好,我写了一个go mysql驱动的一个优化-stmt cache

sam6666666 · 2019-04-08 10:27:42 · 3148 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2019-04-08 10:27:42 的主题,其中的信息可能已经有所发展或是发生改变。

官方对mysql使用标准三步走: sql="insert into users(age) values(?)";

正常的操作是

stmt = db.Prepare(sql)

stmt.Exec(...)

stmt.Close

prepare的时候会先从连接池里取一个连接,然后根据sql语句 创建一个stmt。但是对于同一种数据频繁数据的场景来说,一次prepare就可以了,没必要每次都重写创建一次stmt。

因此在mysqlConn的时候维护一个cache,以sql语句为key,对应的stmt为value。 同一个sql语句直接返回stmt。

当DB.Close的时候,会调用每次mysqlConn的Close,此时遍历cache释放stmt(stmt.Close()) ,释放cache。

具体操作看我github提交的源码。


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3148 次点击  
加入收藏 微博
8 回复  |  直到 2019-04-08 15:04:24
jarlyyn
jarlyyn · #1 · 6年之前

你是不是对prepare有什么误解

正常操作是不需要prepare的

prepare出的stmt本来就是为了多次使用的啊。

sam6666666
sam6666666 · #2 · 6年之前
jarlyynjarlyyn #1 回复

你是不是对prepare有什么误解 正常操作是不需要prepare的 prepare出的stmt本来就是为了多次使用的啊。

考虑下多个协程操作数据库的场景,另外stmt是跟连接绑定的。

jarlyyn
jarlyyn · #3 · 6年之前
sam6666666sam6666666 #2 回复

#1楼 @jarlyyn 考虑下多个协程操作数据库的场景,另外stmt是跟连接绑定的。

文档先确认下啊……

https://golang.org/pkg/database/sql/#Stmt

Stmt is a prepared statement. A Stmt is safe for concurrent use by multiple goroutines.

If a Stmt is prepared on a Tx or Conn, it will be bound to a single underlying connection forever. If the Tx or Conn closes, the Stmt will become unusable and all operations will return an error. If a Stmt is prepared on a DB, it will remain usable for the lifetime of the DB. When the Stmt needs to execute on a new underlying connection, it will prepare itself on the new connection automatically.

sam6666666
sam6666666 · #4 · 6年之前
jarlyynjarlyyn #3 回复

#2楼 @sam6666666 文档先确认下啊…… https://golang.org/pkg/database/sql/#Stmt Stmt is a prepared statement. A Stmt is safe for concurrent use by multiple goroutines. If a Stmt is prepared on a Tx or Conn, it will be bound to a single underlying connection forever. If the Tx or Conn closes, the Stmt will become unusable and all operations will return an error. If a Stmt is prepared on a DB, it will remain usable for the lifetime of the DB. When the Stmt needs to execute on a new underlying connection, it will prepare itself on the new connection automatically.

场景需求,对于多协程+多sql语句的情景下你需要自己维护一个stmt表,而我做的是从mysql驱动层,在每一个mysqlConn里面扩展了一个cache,不需要对原来的代码做修改。

sam6666666
sam6666666 · #5 · 6年之前
jarlyynjarlyyn #3 回复

#2楼 @sam6666666 文档先确认下啊…… https://golang.org/pkg/database/sql/#Stmt Stmt is a prepared statement. A Stmt is safe for concurrent use by multiple goroutines. If a Stmt is prepared on a Tx or Conn, it will be bound to a single underlying connection forever. If the Tx or Conn closes, the Stmt will become unusable and all operations will return an error. If a Stmt is prepared on a DB, it will remain usable for the lifetime of the DB. When the Stmt needs to execute on a new underlying connection, it will prepare itself on the new connection automatically.

唔 我标题起的不太合适了,算不上加速,只是接替了维护sql string和stmt的关系

sam6666666
sam6666666 · #6 · 6年之前
jarlyynjarlyyn #3 回复

#2楼 @sam6666666 文档先确认下啊…… https://golang.org/pkg/database/sql/#Stmt Stmt is a prepared statement. A Stmt is safe for concurrent use by multiple goroutines. If a Stmt is prepared on a Tx or Conn, it will be bound to a single underlying connection forever. If the Tx or Conn closes, the Stmt will become unusable and all operations will return an error. If a Stmt is prepared on a DB, it will remain usable for the lifetime of the DB. When the Stmt needs to execute on a new underlying connection, it will prepare itself on the new connection automatically.

刚在github上讨论了下,原来有个库已经做的了。 https://godoc.org/github.com/Masterminds/squirrel#StmtCache

jarlyyn
jarlyyn · #7 · 6年之前
sam6666666sam6666666 #5 回复

#3楼 @jarlyyn 唔 我标题起的不太合适了,算不上加速,只是接替了维护sql string和stmt的关系

我一开始只是没明白需求点而已。

既然能满足你的需求,就是好库。

至于是否已经有现成的库,其实这部重要。

用库么,要么用最通用的,要么用自己写的。

既然你自己的需求已经到自己需要自己写的程度,其实大概率自己的写更好。

sam6666666
sam6666666 · #8 · 6年之前
jarlyynjarlyyn #7 回复

#5楼 @sam6666666 我一开始只是没明白需求点而已。 既然能满足你的需求,就是好库。 至于是否已经有现成的库,其实这部重要。 用库么,要么用最通用的,要么用自己写的。 既然你自己的需求已经到自己需要自己写的程度,其实大概率自己的写更好。

在理,这个库我看了下,其实实现就是相当于我之前说的维护一个sql语句和stmt的map。。这种就容易犯忘记释放的错误。

所以我倾向于交给驱动层去处理,缺点也显而易见就是太底层了,扩展性不方便。

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传