数据库连接池和事务

背景

在高并发情况下,最近项目中出现了锁定量问题,可能原因是出库没有加上锁定量,入库没有减去锁定量,这样会导致不能正常的出库和入库。需要从几个方面来考虑

1、  业务过程中加锁存在问题

2、  事务没有正确提交

3、  提交了之前不合理的事务

4、  存在没有使用事务的业务

于是在数据库理论基础上,做了一些测试来推断问题所在。首先需要铺垫两方面内容:修改数据库my.ini文件,指定其连接最大等待时间。

默认设置如下:

需要修改wait_timeoutinteractive_timeout。在my.ini中,找到mysqld在其下增加

Wait_timeout=10

Interactive_timeout=10

修改数据库连接池,指定其回收连接最大等待时间。

removeAbandoned="true"

removeAbandonedTimeout="60"

logAbandoned="true"

这样只要两者不相等就可以分别模拟数据库连接关闭和连接池连接关闭情况下事务的执行情况。如下:

数据库连接关闭

用例1

插入test1,插入test2,插入test3,使数据库连接断开在插入test2处并捕获异常,

结论:

异常之后的所有操作都会报错,所有的操作都不能提交到数据库。错误信息如下:

1com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

 

The last packet successfullyreceived from the server was 37,281 milliseconds ago.  The last packet sent successfully to theserver was 0 milliseconds ago.

    atsun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

Caused by: java.net.SocketException: Software caused connection abort: recv failed

    atjava.net.SocketInputStream.socketRead0(Native Method)

2、构造preparedStatement

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.

    atsun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

3、执行

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed.

4、提交事务

java.sql.SQLException: Connection has already been closed.

    atorg.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:117)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

用例2

在用例1基础上,获取同一个连接,并提交事务

结论:

无法获取到同一个连接,当连接关闭后会销毁,下一次请求会创建新连接,因此用例1的未提交事务不会因为用例2的提交被重新提交

数据库连接池连接关闭

用例1

插入test1,插入test2,插入test3,使数据库连接池连接断开在插入test2处并捕获异常,

结论:

异常之后的所有操作都会报错,所有的操作都不能提交到数据库。错误信息如下:

1Connection has been abandoned PooledConnection[com.mysql.jdbc.JDBC4Connection@bc4a53]:java.lang.Exception

    atorg.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:1023)

    atorg.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:689)

    atorg.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:616)

    atorg.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:179)

    atorg.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:126)

2、执行插入:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed.

    atsun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

    atsun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

    atsun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)

    atjava.lang.reflect.Constructor.newInstance(Constructor.java:513)

3、提交事务

java.sql.SQLException: Connection has already been closed.

    atorg.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:117)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

    atorg.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:71)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

    atorg.apache.tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.java:140)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

    atorg.apache.tomcat.jdbc.pool.TrapException.invoke(TrapException.java:41)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

    atorg.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:58)

    at$Proxy4.getAutoCommit(Unknown Source)

    atadultadmin.util.db.DbOperation.commitTransaction(DbOperation.java:142)

用例2

在用例1基础上,获取同一个连接,并提交事务

结论:

无法获取到同一个连接,当连接关闭后连接池会丢弃这个连接,下一次请求会创建新连接,因此用例1的未提交事务不会因为用例2的提交而被重新提交

会造成数据异常原因

正常业务,没有显示进行手动回滚

第一次请求:插入test1,当插入test2时返回并且没有提交事务

第二次请求,获取到同一个连接,插入test1,test2,test3,查询数据库发现test1test2第一次请求的数据被插入

第三次请求,和第一次请求一致

第四次请求,获取不同连接,不会将第三次数据提交到数据库

正常业务,捕获异常后,没有返回

正常业务,没有判断意外,意外发生时没有显示进行手动回滚

没有使用事务

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值