回去认真读了Mybatis源码,发现自己错了,特此更正,以免误导读者,实在是对不起。其实poolMaximumActiveConnections的存在可以正确地限制数据库连接池并发访问数据的连接数,没有问题,之所以我的数据库爆掉了,是我没有正确地维持SqlSessionFactory这个类的一个单例。在使用时一定要保持一个全局唯一的SqlSessionFactory
上次发帖是在跳槽后,今天为止已经在新公司工作了两个星期了,感受什么的,我另外写文章再谈,言归正传,讲正事~~!
目前正在开发一个产品的服务器端代码,持久层我选择了Mybatis3(也就是原来的ibatis)作为框架,之所以选择他理由就是我觉得Hibernate搞起来貌似很复杂,我不太会用,哈哈(上家公司留下的阴影,用Hibernate搞得我想死)。上周完成了大部分代码的开发工作,想着既然是要发布的产品,于是找来Jmeter做压力测试,结果这一测,暴露问题了,mysql返回"
too many connections"这个error,这个error的具体解释参照这个链接
http://dev.mysql.com/doc//refman/5.5/en/too-many-connections.html。
一般持久层与数据库连接都会通过一个连接池(pooled datasource)管理,方便复用连接,控制并发,比较有名的有DBCP,C3P0,BONECP等等。Mybatis3自己实现了一个连接池,在配置文件中指定datasource的type属性为POOLED即可使用。与并发关系较大的两个Mybatis连接池参数是
poolMaximumActiveConnections和
poolMaximumIdleConnections。
好了,出了问题,自然得找文档(官方手册,中英文皆有),poolMaximumActiveConnections是最大的活动连接数,活动连接,顾名思义,就是正在与数据库交互的连接,默认是10,poolMaximumIdleConnections是空闲连接数,就是没有处理请求的连接,默认是5。Mysql的max_connections我设置的是200,既最大连接数。这样一看,好像找不到问题所在,连接池最大的活动连接也就是10,跟200比还差很远,Mysql怎么会返回"too many connections"呢?在查阅文档无果后,我请教周围的一位同事,他虽然没用过Mybatis,但是他说是不是请求数超过poolMaximumActiveConnections后mybatis还会去获取连接,是不是有这样的参数控制,然后让我看看源码,说开源的东西嘛,搞不清楚就看源码。
我一向对源码抱有恐惧的心理,感觉那都是大神写的,我等屌丝怎能看得懂,不过被逼无奈,翻出Mybatis的源码看了一看,结果豁然开朗。找到org.apache.ibatis.datasource.pooled包下面的PooledDataSource类,这个就是连接池的实现类。可以看到里面定义了几个参数,其中就包括poolMaximumActiveConnections和poolMaximumIdleConnections,找到pushConnection方法,这个方法里会判断当前空闲连接数和poolMaximumIdleConnections的大小,如果小于他,会new PooledConnection并放进队列中,这就导致一个问题,当所有的连接被占满后,Mybatis为了保持一定的空闲连接,会不断获取新的连接,然后这些新连接被占用后,就会再去new PooledConnection,结果就是超过了mysql设置的最大连接数,然后数据库返回该错误。不知道这算不算是Mybatis的一个"坑"吧,总之在使用时要小心了,并发量大的时候就会爆掉你的数据库,解决办法很简单,将poolMaximumIdleConnections设置为0即可,果然改掉后压力测试不会爆掉数据库。
现在回想起来,官方文档对poolMaximumIdleConnections的定义是:
在任意时间存在的空闲连接数,完全就解释了这个参数的含义,只不过当时没有仔细想,那这个参数是不是该改名字叫poolPermanentIdleConnections比较好呢,呵呵。
问题解决了,很开心,晚上回去再仔细读下里面的源码,看看还有没有别的没发现的问题。看来源码也不是想象中的那么神秘和高深啊。其实为什么那个同事一下就能看出问题的大概,一方面是经验丰富,另一方面可能与他理解数据库连接池机制有关,归根到底,基础的东西还是最重要的。
分享到:
相关推荐
mybatis 用来建立 sessionFactory 用的,里面主要包含了数据库连接相关东西,还有 java 类所对应的别名,比如 <typeAlias alias="User" type="com.yihaomen.mybatis.model.User"/> 这个别名非常重要,你在 具体的类...
- 在复制本文档中的代码示例时,请注意检查是否有特殊字符(如“引号”和连字符)被自动替换,这些特殊字符可能导致代码无法正常运行。 - 最好从官方提供的下载包或在线文档中复制代码,以确保代码的正确性。 - 如果...
但请注意,MyBatis默认不支持懒加载,需要使用MyBatis的二级缓存或者第三方插件如MyBatis-Plus才能实现。 总结来说,MyBatis的一对一查询提供了灵活且高效的解决方案,通过配置或者注解的方式轻松处理对象间的关联...
3. 其他数据库驱动:虽然资料中特别提到了MySQL,但请注意,如果项目中使用的是Oracle或其他数据库,需要根据实际情况替换对应的数据库驱动jar包。例如,Oracle需要ojdbc.jar,PostgreSQL需要postgresql-jdbc.jar等...
这个案例为我们展示了如何集成这两个强大的框架,并利用MyBatis Plus的自动建表特性简化数据库初始化工作。在实际开发中,可以进一步探索MyBatis Plus提供的其他便利功能,如CRUD操作、条件构造器等,以提高开发效率...
在整合过程中,首先我们需要在 Spring 的应用上下文(application context)中定义两个核心组件:`SqlSessionFactory` 和至少一个数据映射器(Mapper)类。`SqlSessionFactory` 是 MyBatis 中用于创建 SQL 会话对象...
在使用MyBatis批量插入数据到Oracle数据库时,需要将useGeneratedKeys设置为false,以避免主键冲突的错误。 本文分享了MyBatis批量插入数据到Oracle数据库中的两种方式,希望对大家有所帮助。如果您有任何疑问,请...
请注意,这个资源是免费的,供学习和研究使用。 四、实际应用 在实际开发中,Spring与MyBatis的整合能够帮助开发者快速构建数据访问层。例如,在一个用户管理模块,可以通过Mapper接口轻松完成用户查询、添加、修改...
Mybatis 的缓存分为一级缓存和二级缓存两个层次。 1. **一级缓存**: - 一级缓存是 SqlSession 层级的,也称为本地缓存。每当一个新的 SqlSession 创建时,它会拥有一个独立的一级缓存。在同一个 SqlSession 中...
这个简单的例子展示了如何定期检查数据库表的状态,但请注意这并不是真正的实时监听,而是一种轮询机制。实际项目中,你可能需要根据具体需求和数据库类型选择更适合的方法,如使用JDBCN、数据库触发器或第三方库。 ...
在Spring Boot应用中,我们经常会遇到需要连接到多个数据库的需求,比如在微服务架构中,每个服务可能对应一个特定的数据源。本主题将深入探讨如何在Spring Boot中配置和使用多个数据源,以及如何与不同的数据库(如...
同时,确保已将对应的JDBC驱动添加到服务器的类路径中,并在数据库中创建一个名为`test`的表,包含两个字段`test1`和`test2`。 在学习这些基础知识后,随着技能的提升,建议采用更先进的开发模式,例如MVC架构,将...
1. **加载JDBC驱动**:这里使用的是`sun.jdbc.odbc.JdbcOdbcDriver`,但请注意,这个驱动是Oracle JDK的一部分,可能在未来的Java版本中不再支持。 2. **编写Java代码**: ```java try { Connection conn; Class...
方法四: 使用命令运行jar或war,因为也是一个传统JavaWeb项目,前后端不分离,打成jar会无法访问静态资源,所以只能打成war,把WEN-INF下面的东西也打包好) java -jar xxx.war 具体可以自行百度搜索Spring Boot项目的...
请注意,异步任务的执行结果无法直接返回,需要通过Future或者其他机制获取。 5. **部署与运行** 包含了`index.jsp`、`META-INF`、`WEB-INF`和`views`的压缩包文件表明这是一个Web应用。在实际部署时,你需要将...
下载须知: 1. 注意配置相应的jdk版本(jdk1.8)...4. 此项目还实现了跨服务器上传图片的功能(所以压缩包里面有两个工程文件夹),需要运行两个不同端口的Tomcat服务器。 5. 数据库的datasource请按照我的模板自行配置
核心在于重写`determineCurrentLookupKey`方法,这个方法会返回当前应该使用的数据源标识。在这个例子中,数据源的标识通过`DbContextHolder.getDbType()`获取,它可能是由线程上下文存储的用户类型或其他业务相关的...
根据这两个参数,我们可以计算出从数据库中需要获取的数据范围。 1. **分页原理**: - 数据库查询时,利用LIMIT和OFFSET或SQL的ROW_NUMBER()函数来限制返回的结果集,只取特定页的数据。 - 在Java中,通常会有一...