文档章节

golng mysql库连接池分析

r00txx
 r00txx
发布于 09/15 15:40
字数 1164
阅读 20
收藏 0

golng mysql库连接池分析

0x1 背景

golang的协程是好用,但是有时候瓶颈并不在语言上,而是在后面的数据源上面,例如我们常见的mysql,redis等,当一个后端服务很多请求的时候,语言是能hold得住,但是 mysql产生错误,比如 too many connection, too many time_wait 等等这些,今天我们就分析一下怎么解决这种问题

0x2 代码范例

请查看main.go, halokid (有帮忙的话请start或者follow一下哦,谢谢)

0x3 分析

只执行ini函数, 检查mysql的进程显示为(原有的mysql是没有进程在处理的)

没执行前


mysql> show processlist;
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
| Id | User            | Host             | db   | Command | Time | State                  | Info             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
|  4 | event_scheduler | localhost        | NULL | Daemon  | 2304 | Waiting on empty queue | NULL             |
|  9 | root            | 10.244.1.1:64000 | test | Sleep   | 1315 |                        | NULL             |
| 10 | root            | 10.244.1.1:64022 | test | Query   |    0 | starting               | show processlist |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
3 rows in set (0.01 sec)

执行后


mysql> show processlist;
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
| Id | User            | Host             | db   | Command | Time | State                  | Info             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
|  4 | event_scheduler | localhost        | NULL | Daemon  | 2284 | Waiting on empty queue | NULL             |
|  9 | root            | 10.244.1.1:64000 | test | Sleep   | 1295 |                        | NULL             |
| 10 | root            | 10.244.1.1:64022 | test | Query   |    0 | starting               | show processlist |
| 13 | root            | 10.244.1.1:52134 | test | Sleep   |   20 |                        | NULL             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
4 rows in set (0.00 sec)


可见执行 db.Ping() 之后, process多了一个 Sleep 的连接,就是放了一个连接进 连接池

运行

db.SetMaxOpenConns(10)
db.SetMaxIdleConns(5)

两句之后, 连接池并没有改变, 可见上面的逻辑是在 数据库处理逻辑真实执行的时候才生效的

执行协程查询

mysql> show processlist;
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
| Id | User            | Host             | db   | Command | Time | State                  | Info             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
|  4 | event_scheduler | localhost        | NULL | Daemon  | 4397 | Waiting on empty queue | NULL             |
|  9 | root            | 10.244.1.1:64000 | test | Sleep   | 3408 |                        | NULL             |
| 10 | root            | 10.244.1.1:64022 | test | Query   |    0 | starting               | show processlist |
| 19 | root            | 10.244.1.1:54823 | test | Sleep   |  952 |                        | NULL             |
| 20 | root            | 10.244.1.1:54824 | test | Sleep   | 1104 |                        | NULL             |
| 47 | root            | 10.244.1.1:57906 | test | Sleep   |    0 |                        | NULL             |
| 48 | root            | 10.244.1.1:57909 | test | Sleep   |    0 |                        | NULL             |
| 49 | root            | 10.244.1.1:57912 | test | Sleep   |    0 |                        | NULL             |
| 50 | root            | 10.244.1.1:57907 | test | Sleep   |    0 |                        | NULL             |
| 51 | root            | 10.244.1.1:57908 | test | Sleep   |    0 |                        | NULL             |
| 52 | root            | 10.244.1.1:57913 | test | Sleep   |    0 |                        | NULL             |
| 53 | root            | 10.244.1.1:57911 | test | Sleep   |    0 |                        | NULL             |
| 54 | root            | 10.244.1.1:57910 | test | Sleep   |    0 |                        | NULL             |
| 55 | root            | 10.244.1.1:57915 | test | Sleep   |    0 |                        | NULL             |
| 56 | root            | 10.244.1.1:57914 | test | Sleep   |    0 |                        | NULL             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
15 rows in set (0.00 sec)

执行完在等待

mysql> show processlist;
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
| Id | User            | Host             | db   | Command | Time | State                  | Info             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
|  4 | event_scheduler | localhost        | NULL | Daemon  | 3931 | Waiting on empty queue | NULL             |
|  9 | root            | 10.244.1.1:64000 | test | Sleep   | 2942 |                        | NULL             |
| 10 | root            | 10.244.1.1:64022 | test | Query   |    0 | starting               | show processlist |
| 19 | root            | 10.244.1.1:54823 | test | Sleep   |  486 |                        | NULL             |
| 20 | root            | 10.244.1.1:54824 | test | Sleep   |  638 |                        | NULL             |
| 32 | root            | 10.244.1.1:56588 | test | Sleep   |   22 |                        | NULL             |
| 33 | root            | 10.244.1.1:56591 | test | Sleep   |   22 |                        | NULL             |
| 34 | root            | 10.244.1.1:56589 | test | Sleep   |   22 |                        | NULL             |
| 35 | root            | 10.244.1.1:56590 | test | Sleep   |   22 |                        | NULL             |
| 36 | root            | 10.244.1.1:56592 | test | Sleep   |   22 |                        | NULL             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
10 rows in set (0.00 sec)

协程执行完之后

mysql> show processlist;
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
| Id | User            | Host             | db   | Command | Time | State                  | Info             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
|  4 | event_scheduler | localhost        | NULL | Daemon  | 3941 | Waiting on empty queue | NULL             |
|  9 | root            | 10.244.1.1:64000 | test | Sleep   | 2952 |                        | NULL             |
| 10 | root            | 10.244.1.1:64022 | test | Query   |    0 | starting               | show processlist |
| 19 | root            | 10.244.1.1:54823 | test | Sleep   |  496 |                        | NULL             |
| 20 | root            | 10.244.1.1:54824 | test | Sleep   |  648 |                        | NULL             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
5 rows in set (0.00 sec)

我们发现最大连接控制在了10个, 执行完之后还有5个连接在保持着

这里有一个很重要的问题,就是连接池的过期时间

0x4 深入分析 我们把 db.SetConnMaxLifetime(15 * time.Second), 连接池连接的生命周期设置为 15秒, 我们会发现15秒之后,连接池的连接都会断掉

mysql> show processlist;
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
| Id | User            | Host             | db   | Command | Time | State                  | Info             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
|  4 | event_scheduler | localhost        | NULL | Daemon  | 4987 | Waiting on empty queue | NULL             |
|  9 | root            | 10.244.1.1:64000 | test | Sleep   | 3998 |                        | NULL             |
| 10 | root            | 10.244.1.1:64022 | test | Query   |    0 | starting               | show processlist |
| 19 | root            | 10.244.1.1:54823 | test | Sleep   | 1542 |                        | NULL             |
| 20 | root            | 10.244.1.1:54824 | test | Sleep   | 1694 |                        | NULL             |
+----+-----------------+------------------+------+---------+------+------------------------+------------------+
5 rows in set (0.00 sec)

30秒之后再次查询数据库

time.Sleep(30 * time.Second)
  rows, err := db.Query("select name from users")
  fmt.Println("err -----", err)
  defer rows.Close()
  for rows.Next(){
    var name string
    rows.Scan(&name)
    fmt.Println("name---", name)
  }

这个时候发现程序会重新发起新的db连接

总结:

mysql服务端的连接生命周期

还有一种请况就是,我们的程序的连接池生命周期设置大于mysql服务器的生命周期设置, 这个时候就会有一种请况,假如我们重复用连接池的连接,会产生 连接错误的问题,解决方法有两种:

  1. 可以在程序里面设置生命周期时间小于mysql服务端的连接生命周期时间就可以了
  2. 增加程序的重连(keepalive)机制,就是定时发送一个连接包服务端 关于第2点我们我们以后可以再发散来说,一般如果允许的话,用第一种方式即可。
mysql> show variables like 'mysqlx_wait_timeout';
+---------------------+-------+
| Variable_name       | Value |
+---------------------+-------+
| mysqlx_wait_timeout | 28800 |
+---------------------+-------+
1 row in set (0.00 sec)

© 著作权归作者所有

r00txx
粉丝 1
博文 23
码字总数 10973
作品 0
广州
架构师
私信 提问
MySql 基于C_API的数据库封装

单线程程序的数据库访问 (1)初始化MySQL库   (2)初始化数据库连接句柄   (3)连接数据库   (4)通过SQL语句操作数据库并处理相应数据   (5)关闭数据库连接   (6)结束MySQL库   通过...

吃一堑消化不良
2016/09/27
127
0
SMProxy,让你的数据库操作快三倍!

中文 | English SMProxy 喜欢请star github: https://github.com/louislivi/smproxy Swoole MySQL Proxy 一个基于 MySQL 协议,Swoole 开发的MySQL数据库连接池。 原理 将数据库连接作为对象...

louislivi
2018/12/07
0
0
在Java中开源的数据库连接池

在Java中开源的数据库连接池有以下几种 : 1, C3P0 C3P0是一个开放源代码的JDBC连接池,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。 https://gith...

壶漏子
2015/09/28
268
0
数据库连接池种类,你会那种??

在Java中开源的数据库连接池有以下几种 : 1, C3P0 C3P0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate[1]一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement...

一一叶
2014/03/11
747
1
使用hibernate 数据库连接数增多

用的springmvc+spring4+hibernate4 程序跑起来之后 观察 mysql 的连接数 如下: 目前用的jdni 还没有配置连接池。出现以下情况后 项目可以正常访问 问题:1,以下 单库 有9个连接长期 处于s...

zhaiguangtao
2015/04/15
515
0

没有更多内容

加载失败,请刷新页面

加载更多

Phpstorm2018 永久激活

1、安装phpstorm,安装包请自行官网下载 http://www.jetbrains.com/phpstorm/download/ 2、下载JetbrainsCrack.jar文件,存放至你的phpstorm执行文件同级目录下 下载JetbrainsCrack.jar 提取...

happyfish319
11分钟前
3
0
谈一谈Android进程间通信的几种方式

###来看一下Android中除了AIDL还有哪些进程间通信的方式: 1、Bundle Bundle实现了Parcelable,所以在Android中我们可以通过Intent在不同进程间传递Bundle数据。 但是在Intent 传输数据的过程...

二营长的意大利炮手
12分钟前
4
0
互联网薪资“高开低走”,你的能力是否真的可以匹配高薪?

对于国内外主流互联网大厂,技术出身似乎已经成为各大掌门人的必备标签。谷歌 CEO 桑达尔·皮查伊、马克·扎克伯格、李彦宏、马化腾、雷军等等皆为技术人出身,都曾参与了公司内部重要产品的...

Java技术剑
14分钟前
2
0
java 多线程

线程声明周期 线程的五个状态:新建,就绪,运行,阻塞,死亡。 其中就绪和运行两个状态客户互相转换,但运行到阻塞,阻塞到就绪,只能单向转换。 刚new出的线程就是【新建】状态,调用start...

雷开你的门
15分钟前
4
0
构造器Constructor是否可被overrid

构造器不能被重写,不能用static修饰构造器,只能用public private protected这三个权限修饰符,且不能有返回语句。

无名氏的程序员
19分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部