目录

一、数据库连接数基本知识

1.查看默认连接数

2.修改默认连接数

3.查看数据库当前连接数

二、jmeter压测数据库

三、druid连接池

1.连接池配置

2.查看配置是否生效


一、数据库连接数基本知识

1.查看默认连接数

mysql默认最大连接数最大值为:151

语句:

 show variables like '%connections%';

show variables like '%max_connections%';

2.修改默认连接数

语句:set GLOBAL max_connections=50;

修改mysql默认连接数,然后查看如下:

3.查看数据库当前连接数

查看当前和数据库建立的连接数:

语句:show status like 'Threads%';
 

  • Threads_cached:线程缓存内的线程数量
  • Threads_connected:当前打开的连接数量, Threads_connected 跟show processlist结果相同
  • Threads_created:创建的线程数
  • Threads_running:正在运行的线程数(激活的连接数),这个数值一般远低于connected数值;准确的来说, Threads_running是代表当前并发数

执行命令如下:

show PROCESSLIST;

总共46条记录,其中一条状态为starting的就是当前执行的这条语句

 通过show status like 'Threads%';语句也看到,刚好是46个连接,和show PROCESSLIST;显示的数量一致。

另一个解释:

三个参数,一个是treads_cached这个是缓冲池中的线程个数。还有一个是treads_connected这个是连接中的线程数。第三个是Threads_created,它的含义是已经创建的线程数。在并发数低的情况下,一般Threads_created参数是treads_cached和treads_connected参数之和。当并发数高的情况下,Threads_created就会暴增,这个时候就需要考虑thread_cache_size来设置缓冲池的大小了。

二、jmeter压测数据库

先把最大连接数改小一点,方便连接数达到峰值,这里改为50。

jmeter如下:500个线程,每个线程循环50次:

如下,请求获取用户列表的接口,即数据库一直在执行查询操作 

启动,此时一直查询,然后查看数据库连接数如下:已经51了,此时就满了,不管发多少个请求数据库连接数都不会再增加 了

并且jmeter一直发请求,导致连接数过多,后端代码会报错,如下:

提示连接数过多:Too many connections

java.sql.SQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110) ~[mysql-connector-java-8.0.30.jar:8.0.30]
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.30.jar:8.0.30]
	at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:828) ~[mysql-connector-java-8.0.30.jar:8.0.30]
	at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:448) ~[mysql-connector-java-8.0.30.jar:8.0.30]
	at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) ~[mysql-connector-java-8.0.30.jar:8.0.30]
	at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198) ~[mysql-connector-java-8.0.30.jar:8.0.30]
	at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1678) ~[druid-1.2.12.jar:1.2.12]
	at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1755) ~[druid-1.2.12.jar:1.2.12]
	at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2825) ~[druid-1.2.12.jar:1.2.12]

直接查询数据库时也无法查询了 ,提示连接数过多,因为打开Navicat执行一次查询语句,也是一个连接数。

修改连接数也不行,因为执行修改语句也要占用一个连接

 此时需要等待连接数释放,或者重启数据库服务器。等待连接数释放还有一种方案,就是把链接数据库的服务器停掉,比如后端的一个springboot服务连接的数据库连接数满了,直接把springboot服务停止调,让别人无法通过该服务连接数据库,等一会儿,等待连接数失效释放即可。

我把springboot服务停止十几分钟,执行如下两条查询语句都不行,仍然提示连接数满了

 重启springboot服务提示满了

 这是为啥呢?过了十几分钟仍然没有释放连接。暂时猜测是最大空闲时间太长,导致连接十几分钟后还没有释放,先重启mysql服务,如下,我是用docker容器启动的:

再次查询sql:

已经正常查询如下:并且连接数为1,创建的线程为1,正在执行的线程也是1,这个1就是当前执行的这条语句

查询一个表也正常了:

再次查看,连接数和创建的线程就是2了,因为上一条加这一条就是两条连接了:

三、druid连接池

1.连接池配置

# mysql数据源
spring:
  # 允许循环依赖 暂时这么解决 后面抽时间再处理
  main:
    allow-circular-references: true
    #easypoi 自动配置类和springboot自动配置类bean冲突解决
    allow-bean-definition-overriding: true

  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://113.250.xxx.xxx:3306/environment?serverTimezone=GMT%2B8&characterEncoding=utf8&useSSL=true
    username: xxxx
    password: xxxx
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 5
      min-idle: 5 #最小连接池数量
      max-active: 20 #最大连接池数量
      max-wait: 6000 #获取连接时最大等待时间,单位毫秒
      min-evictable-idle-time-millis: 600000 #配置一个连接在池中最小生存的时间,单位是毫秒 10分钟
      max-evictable-idle-time-millis: 900000 #配置一个连接在池中最大生存的时间,单位是毫秒 15分钟
      time-between-eviction-runs-millis: 6000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      test-while-idle: true #如果为true(默认true),当应用向连接池申请连接,并且testOnBorrow为false时,连接池将会判断连接是否处于空闲状态,如果是,则验证这条连接是否可用
      test-on-borrow: false #验证连接,配合test-while-idle使用
      test-on-return: false #当应用使用完连接,连接池回收连接的时候会判断该连接是否还可用

可以参考阿里巴巴给的通用配置:

DruidDataSource配置 · alibaba/druid Wiki · GitHub

2.查看配置是否生效

写一个测试类,打断点看看dataSource类,查看数据源配置的东西是否都确实生效了。

package com.tn.humanenv;

import com.alibaba.fastjson.JSON;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import javax.sql.DataSource;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class MonsterlanApplicationTests {
   @Autowired
   DataSourceProperties dataSourceProperties;
   @Autowired
   ApplicationContext applicationContext;

   /*也可以直接依赖DataSource*/
   @Autowired
   DataSource dataSource1;
   @Test
   public void contextLoads() {
      // 获取配置的数据源
      DataSource dataSource = applicationContext.getBean(DataSource.class);
      // 查看配置数据源信息
      System.out.println(dataSource);
      System.out.println(dataSource.getClass().getName());
      System.out.println(dataSourceProperties);
      System.out.println(dataSource.getClass());
      System.out.println(dataSource.getClass().getName());
      //执行SQL,输出查到的数据
      JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
      List<?> resultList = jdbcTemplate.queryForList("select * from sys_user");
      System.out.println("===>>>>>>>>>>>" + JSON.toJSONString(resultList));
   }
}

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐