记一次mysql连接数问题

最近在做离线采集的东西,在做采集的过程中,时不时遇到mysql连接数满了,于是排查了一下原因。

1 事故现场

1
too many connections

背景是这样的,最近做的东西是采集RDBMS的数据到HIVEIMPALAKUDUHBASE。目前我们用的RDBMS主要是mysql和oracle。

场景是通过JDBC去访问HIVE,创建HIVE和MYSQL的StorageHandler外联表,然后经常就遇到·mysql连接数满了·,而且很频繁。

加上这块代码是我撸的,心里顿时慌的一批,赶紧去看一下。

2 故障排查

2.1 代码排查

想都不用想,连接数的问题,直接找到JDBC连接的地方(下面代码我把所有业务逻辑全去了,只留主要的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import org.apache.tomcat.jdbc.pool.DataSource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DataSourceTest {
public static void main(String[] args) {
DataSource dataSource = new DataSource();
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306");
dataSource.setUsername("root");
dataSource.setPassword("root");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 获得连接
try {
Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("show databases");
// 关闭连接
resultSet.close();
statement.close();
connection.close();
} catch (SQLException exception) {
exception.printStackTrace();
}
// 在这里打断点模拟web项目
System.out.println("给爷停在这里,Fuck You!");
}
}

pom

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>10.1.0-M5</version>
</dependency>

一开始我想着,我这结果集执行语句连接全都关了呀,感觉没啥问题呀,有点怀疑是不是我的问题

于是跑到数据库去观察。

2.2 数据库排查

随便搞个数据库测试下。

2.2.1 查看最大连接数

1
2
3
4
5
6
7
mysql> SHOW VARIABLES LIKE '%max_connections%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
1 row in set (0.01 sec)

发现是默认的151

2.2.2 查看当前连接数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
mysql> SHOW STATUS LIKE 'Threads%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_cached | 1 |
| Threads_connected | 16 | # 打开的连接数,这个到151就爆了
| Threads_created | 19 |
| Threads_running | 3 | # 激活的连接数,一般远低于connected
+-------------------+-------+
4 rows in set (0.00 sec)


也可以用下面命令查看连接详细信息:这个数值和Threads_connected一致。


mysql> SHOW FULL PROCESSLIST;
+----+------+---------------------+---------------+-------------+------+---------------------------------------------------------------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+---------------------+---------------+-------------+------+---------------------------------------------------------------+-----------------------+
| 2 | root | 172.18.17.22:10354 | canal_manager | Sleep | 43 | | NULL |
| 3 | qiao | dbus-n3:39416 | NULL | Binlog Dump | 567 | Master has sent all binlog to slave; waiting for more updates | NULL |
| 26 | root | 172.18.17.49:54266 | test_schema1 | Sleep | 10 | | NULL |
| 27 | root | 172.18.17.49:54267 | test_schema1 | Sleep | 495 | | NULL |
| 28 | root | 172.18.26.237:49224 | NULL | Query | 0 | starting | SHOW FULL PROCESSLIST |
| 29 | root | 172.18.17.49:62920 | NULL | Binlog Dump | 379 | Master has sent all binlog to slave; waiting for more updates | NULL |
| 30 | root | 172.18.17.49:62921 | NULL | Sleep | 378 | | NULL |
| 31 | root | 172.18.17.49:62922 | NULL | Sleep | 378 | | NULL |
| 32 | root | 172.18.17.49:62923 | NULL | Sleep | 378 | | NULL |
| 33 | root | 172.18.17.49:62924 | NULL | Sleep | 378 | | NULL |
| 34 | root | 172.18.17.49:62925 | NULL | Sleep | 378 | | NULL |
| 35 | root | 172.18.17.49:62926 | NULL | Sleep | 378 | | NULL |
| 36 | root | 172.18.17.49:62927 | NULL | Sleep | 378 | | NULL |
| 37 | root | 172.18.17.49:62928 | NULL | Sleep | 378 | | NULL |
| 38 | root | 172.18.17.49:62929 | NULL | Sleep | 378 | | NULL |
| 39 | root | 172.18.17.49:62930 | NULL | Sleep | 376 | | NULL |
+----+------+---------------------+---------------+-------------+------+---------------------------------------------------------------+-----------------------+
16 rows in set (0.00 sec)

2.2.3 场景还原

给我代码最后一行打断点,跑起来。

一跑问题就出来了,发现连接数从16变成了26多了10个连接。

3个线程试一下,一下子多了30个连接这他娘真是我代码问题了

回想了一下,以前写jdbc用的DriverManager,这次换成了DataSource,点进DataSource源码一看,我尼玛,原来是个连接池

再看一下,连接池默认大小是10,这问题就柳暗花明又一村了。

问题找到了,那就开始灭他满门吧。

3 事故处理

总结下来有两个问题:

一是我使用完连接池后没有关闭,这也是经常爆的原因。

二是每次跑我并不需要10个连接数,可能只用到两三个,所以缩小连接池的大小。

修改后的代码如下(没有提取封装,只做demo测试)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DataSourceTest {
public static void main(String[] args) {
// 连接池设置
PoolProperties properties = new PoolProperties();
properties.setInitialSize(3);
// 获得连接池
DataSource dataSource = new DataSource(properties);
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306");
dataSource.setUsername("root");
dataSource.setPassword("root");
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
// 获得连接
try {
Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("show databases");
// 关闭连接
resultSet.close();
statement.close();
connection.close();
} catch (SQLException exception) {
exception.printStackTrace();
} finally {
// 关闭连接池
dataSource.close();
}
// 在这里打断点模拟web项目
System.out.println("给爷停在这里,Fuck You!");
}
}

问题解决了,先干饭吧

4 躺板板

红伞伞白杆杆,吃完一起躺板板

躺板板埋山山,亲朋都来吃饭饭

饭饭里有红伞伞,吃完全村埋山山,来年长满红伞伞

联系博主,加入【羊山丨交流社区】

联系博主


本博客所有文章除特别声明外,均为原创。版权归博主小马所有。任何团体、机构、媒体、网站、公众号及个人不得转载。如需转载,请联系博主(关于页面)。如其他团体、机构、媒体、网站、博客或个人未经博主允许擅自转载使用,请自负版权等法律责任!