最近,项目中遇到了数据库连接不够的问题。

异常信息com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:

Data source rejected establishment of connection,  message from server: "Too many connections"

根据更详细的错误信息,我定位到报错的函数位置。

关键函数/**

* 判断数据库是否存在

*/

public boolean hasDatabaseByKey(String name) {

boolean containsKey = dataSourceMap.containsKey(name);

if (containsKey) {

try {

//根据数据库名称,把BoneCP数据源中的数据库参数取出来,用户名、密码、URL

Object obj = dataSourceMap.get(name);

com.jolbox.bonecp.BoneCPDataSource dataSource = (com.jolbox.bonecp.BoneCPDataSource) obj;

String password = dataSource.getPassword();

String username = dataSource.getUsername();

String url = dataSource.getJdbcUrl();

//建立新的数据库连接--这一行代码抛出“Too many connections”异常

Connection con = DriverManager.getConnection(url, username, password);

//关闭连接

if (con != null) {

con.close();

}

return true;

} catch (Exception e) {

LOG.error("Database name error:" + name);

e.printStackTrace();

}

}

return false;

}

是否正常关闭了数据库连接

上述代码的主要功能是,根据前端传入的数据库名字,如“test”,检测该数据库的配置是否正确。

最初想到的,上面的数据库连接con可能没有正常关闭。

经过单步跟踪debug,和使用MySQL的 show processlist命令,发现所有的连接确实是正常关闭的。

因此,上述代码的功能是没有问题的。

功能没有问题,但是上述代码还是存在其它问题的

a.数据库连接应该在finally里关闭。

b.这种检测方法,每次都需要打开一个连接,比较耗费时间。

一种好的方法是,在系统初始化的时候,检查所有的数据源配置是否正确,把结果

用Map保存起来,("test",true)表明test数据库配置正确;

或者每一次检查,先从缓存中取,如果存在直接使用,否则,打开连接,进行检查,然后保存结果到缓存中。

问题根源

项目中使用了多个数据库, 数据源公共的配置如下。

最近新增了10个数据源配置。

也就是说,现在新增的数据库连接,最高可以达到50*(10+1)=550个了。(不是50*1=50个)

而数据库MySQL的默认max_connections是100。

因此,我们在访问Web项目,然后频繁切换项目的时候,数据库连接池中的数目,已经达到了100。

这个时候,我们再去手动创建数据库连接,就会失败。

上文代码的更多配置信息@Resource

private Map dataSourceMap;

value="jdbc:mysql://ip:3306/demo1?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull" />

value="jdbc:mysql://ip:3306/demo2?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull" />

改进后的代码private static Map databaseStatusMap = new HashMap();

/**

* 判断数据库是否存在

*/

public boolean hasDatabaseByKey(String name) {

//数据源中是否含有这个数据库名称

boolean containsKey = dataSourceMap.containsKey(name);

//不存在这个数据名字,直接false

if (!containsKey) {

return false;

}

//首先从缓存中拿,不为null,表明已经验证过了

Boolean status=databaseStatusMap.get(name);

if(status != null){

return status;

}

//缓存中不存在,第1次验证

boolean databaseConfigSucceed = false;

Connection con = null;

try {

Object obj = dataSourceMap.get(name);

com.jolbox.bonecp.BoneCPDataSource dataSource = (com.jolbox.bonecp.BoneCPDataSource) obj;

String password = dataSource.getPassword();

String username = dataSource.getUsername();

String url = dataSource.getJdbcUrl();

//验证数据库连接,把结果存到缓存中

con = DriverManager.getConnection(url, username, password);

//这个地方con不可能为null,要么是一个正常的连接,要么抛出异常

databaseConfigSucceed = true;

databaseStatusMap.put(name, true);

/*

if (con != null) {

databaseConfigSucceed = true;

databaseStatusMap.put(name, true);

}

else{

databaseConfigSucceed = false;

databaseStatusMap.put(name, false);

}*/

} catch (Exception e) {

//抛出异常,下次不会去重新检查,可能会存在bug,如果第1次检测的时候,网断了或者MySQL挂了或者数据库连接过多,并不能代表配置不正确

//小概率事件,暂时不考虑

LOG.error("Database name error:" + name);

databaseConfigSucceed=false;

databaseStatusMap.put(name, false);

e.printStackTrace();

} finally {

if (con != null) {

try {

//验证完数据库连接,需要手动关闭

con.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

return databaseConfigSucceed;

}

小概率事件

如果在执行 DriverManager.getConnection(url, username, password);获取数据库连接的时候,发生了异常。

如果恰好是第1次检测的时候,网断了或者MySQL挂了或者数据库连接过多,并不能代表配置不正确。

抛出异常,下次就不会去重新检查,可能会存在bug。

不过,系统第一次访问项目的时候,正好出故障的可能性很低。

可能存在的错误情况:

第一次成功,加入缓存为true,如果今后数据库连接打不开,应该提示“不可以打开”,也会提示“可以打开”。

第一次不成功,加入缓存为false,如果今后数据库能够打开,应该提示“可以打开”,也会提示“不可以打开”。

结论

1.在不使用缓存的情况下,每次都通过建立新连接的方式。

优点:可以准确的判断数据库配置是否正确,是否真正能够连接到数据库,代码的可读性和复杂度比较低。

缺点:性能比较差。

2.使用缓存。

优点:性能比较高。

缺点:在不正常情况下,准确性没有保障。代码的可读性和复杂度比较高。

再次改进

缓存,增加“时间限制”,过一段时间后,就失效。

观点

实现的功能越多,越准确,性能越好,代码可能会越来越复杂。

代码的正确性和性能有的时候是“互相排斥”的。

过多的追求完美,也会带来一些负担。

mysql 数据库连接不够_一个Web报表项目的性能分析和优化实践(二):MySQL数据库连接不够用(TooManyConnections)问题的一次分析和解决案例...相关推荐

  1. 一个Web报表项目的性能分析和优化实践(七):性能监测工具JavaMelody

    简介 JavaMelody 能够监测Java或Java EE应用程序服务器,并以图表的方式显示: Java内存和Java CPU使用情况,用户Session数量,JDBC连接数, 和http请求.sq ...

  2. mysql 数据库连接不够_(二):MySQL数据库连接不够用(TooManyConnections)问题的一次分析和解决案例...

    # (二):MySQL数据库连接不够用(TooManyConnections)问题的一次分析和解决案例 最近,项目中遇到了数据库连接不够的问题. **异常信息** com.mysql.jdbc.exc ...

  3. 一个真实项目的性能分析策略

    作为性能工程师或性能团队负责人,你敢拍着胸脯说:"这个系统'死'了我负责!我卷铺盖走人!"吗? 如果你敢这么说,得到的薪资待遇肯定不一样.可是,在当前的性能市场中,谁敢给出这样的业 ...

  4. mysql group 更新递增_MySQL Group Replication在网易使用和优化实践

    本文由作者授权网易云发布,未经许可,请勿转载 作者:温正湖,网易数据库技术专家 MGR(MySQL Group Replication)是MySQL官方推出的领先的服务高可用和数据高可靠方案,网易从2 ...

  5. mysql 用户名 长度_一个 MySQL 用户名长度的坑

    今天使用 PHP 连接一个 MySQL 数据库的时候连不上,提示无权限. 因为 MySQL 是在另外一个机房,首先想到的是防火墙的原因,但使用 MySQL-cli 却能正常连接,遂排除这种可能. 又怀 ...

  6. 阿里云搭建一个web项目(网站)介绍(Apache+php+MySQL)

    1.从阿里云购买一个ecs服务器 进入阿里云官方平台https://home.console.aliyun.com,选择左侧导航云服务器ECS 选择导航中的实例: 点击右上角的创建实例按钮: 购买界面 ...

  7. delete mysql 大表_无语了,直到今天,我才揪出MySQL磁盘消耗迅猛的“真凶”!

    作者:dbapower 链接:https://blog.51cto.com/suifu/2135599 背景 Part1:写在最前 当一张单表10亿数据量的表放在你面前,你将面临着什么? Part2: ...

  8. mysql 开发 生产_在没有表锁定的情况下在巨大的MySQL生产表...

    [2017]更新:MySQL 5.6支持在线索引更新 In MySQL 5.6 and higher, the table remains available for read and write o ...

  9. mysql写系统_一个用PHP和MYSQL写的定饭系统_PHP

    前台html 定饭 http://www.gaodaima.com/66512.html一个用php和mysql写的定饭系统_PHP vlink="#3366CC" alink=& ...

最新文章

  1. CMake的几种Include
  2. 【Mybatis 之应用篇】2_配置解析、属性名问题、日志、分页和注解开发
  3. 【项目实践】【01】发货管理系统 SPS (2007年12月23日更新)
  4. [Medical Image Processing] 2. Image Binary -【OTSU Algorithm Entropy Method】
  5. 这里有一份面筋请查收(七)
  6. 大剑无锋之TCP和UDP区别【面试推荐】
  7. ora-01591:锁被未分布式事物处理/Distrib tran
  8. 2015.8.3 Java
  9. 彭国伦Fortran95学习笔记(一)第八章至第十六章
  10. 前端上传视频至阿里云并转码
  11. java读取gpx文件,读取GPX文件+optpars的简单python脚本
  12. 批处理html转excel,批量Excel转TXT工具(Batch Excel to Text Converter)v2020.12.1118官方免费版...
  13. 大型互联网公司如何自建拥有独立AS号的IP网络
  14. Java制作PDF转图片小工具
  15. Xcode如何实现iphone真机测试
  16. Apache Kafka(七)- Kafka ElasticSearch Comsumer
  17. python鸭子类型_1
  18. Lasso回归理论及代码实现
  19. IDEA如何配置 Gradle 及 Gradle 安装过程(详细版)
  20. C#的循环控制语句(break,continue)语句

热门文章

  1. 那个分分钟处理 10 亿节点图计算的 Plato,现在怎么样了?
  2. 惊艳!Uber 的豪华开源深度学习“全家桶”
  3. 这些硬核公众号你知道几个?
  4. 程序员为什么非得参加一场编程竞赛?
  5. 惊呆!这辆悍马自己在跑跑跑跑跑跑跑!
  6. 硬核软件开发者 30 多年的 11 条经验教训
  7. Google Flutter 一统移动、Web、桌面、嵌入式江湖!
  8. 开了个会:破局企业云通信,华为加速 Buff 开发者!
  9. 如何用 Python 解读著名的“三门问题”?
  10. 因代码不规范,码农枪击4名同事,一人情况危急