由JDBC事务引起的锁状态以及内存数据无法写入数据库的问题
2017-09-19 19:48
477 查看
最近在做项目的时候,踩了一个大坑,为了排查BUG所在,花费了大量的时间。所以觉得应该来一个“填坑之路”系列,自己踩过的坑,希望各位看官能及时绕开。得亏看到了,要不然踩着了!
事情是这样的,开发完成的一个项目,在本地测试表现正常,没有问题。但在发布到服务器上之后,问题就出现了,一开始会出现用户添加的数据无法写入数据库的情况,重启数据库之后,一段时间内数据可以及时写入,但一段时间之后又会出现内存中数据无法写入数据库的情况。具体表现为:在Web页面写入数据后,可以在页面看到数据的变化,但进入数据库查询却看不到任何改变。另外,在整个系统访问人数增多之后,会不时地出现事务锁的情况,后台报错为:数据库等待超时或数据库出现死锁。
之后就是分析问题,然后各种猜测:数据库版本不对?数据库配置缓存区设置过大?数据库自动提交默认关闭?数据库引擎问题?数据源连接池采用了单例模式?在排除了以上所有可能之后,我看到了一行代码
会不会是这里我要开启事务因而关闭自动提交的原因?但是下面还有一行呢
按理说,我关闭了当前连接,下次建立的又是一个新的连接,数据库又是默认开启自动提交的,所以这样写应该是完全合理的啊。但目前能想到的也只剩这么一个可能了,我不确定是不是这个原因所致,因此我做了一个实验:
从网页上登录系统,首先进行一项需要开启事务的sql语句相关的操作,然后观察数据库是否能及时写入数据,发现写入正常。接下来,无论执行怎样的操作,发现数据库都已经无法及时地写入数据。这下困扰我许久的问题应该水落石出了:在执行了
总结一下,如果数据库操作要用到事务的话(批量操作需要用事务大家都知道的吧?不然每一条数据改动都提交一次会严重影响效率,采用事务在所有数据更改完毕之后一次性提交),以下代码必不可少,且必须按顺序执行:
事情是这样的,开发完成的一个项目,在本地测试表现正常,没有问题。但在发布到服务器上之后,问题就出现了,一开始会出现用户添加的数据无法写入数据库的情况,重启数据库之后,一段时间内数据可以及时写入,但一段时间之后又会出现内存中数据无法写入数据库的情况。具体表现为:在Web页面写入数据后,可以在页面看到数据的变化,但进入数据库查询却看不到任何改变。另外,在整个系统访问人数增多之后,会不时地出现事务锁的情况,后台报错为:数据库等待超时或数据库出现死锁。
之后就是分析问题,然后各种猜测:数据库版本不对?数据库配置缓存区设置过大?数据库自动提交默认关闭?数据库引擎问题?数据源连接池采用了单例模式?在排除了以上所有可能之后,我看到了一行代码
conn.setAutoCommit(false);
会不会是这里我要开启事务因而关闭自动提交的原因?但是下面还有一行呢
if (conn != null) { conn.close(); }
按理说,我关闭了当前连接,下次建立的又是一个新的连接,数据库又是默认开启自动提交的,所以这样写应该是完全合理的啊。但目前能想到的也只剩这么一个可能了,我不确定是不是这个原因所致,因此我做了一个实验:
从网页上登录系统,首先进行一项需要开启事务的sql语句相关的操作,然后观察数据库是否能及时写入数据,发现写入正常。接下来,无论执行怎样的操作,发现数据库都已经无法及时地写入数据。这下困扰我许久的问题应该水落石出了:在执行了
conn.setAutoCommit(false);这句代码之后,连接即使关闭了,之后建立的新连接的自动提交都为关闭状态。但是为什么呢?网上查阅资料后发现,数据源采用连接池执行
conn.close();语句,并不是真正关闭连接,而是将连接归还连接池,供下次使用。真相大白之后,接下来的修改就简单啦,在finally语句块中添加
conn.setAutoCommit(true);将自动提交手动开启。另外,需要特别注意的是:如果采用了事务,那么必须在catch语句块中添加
conn.rollback();进行数据库回滚。否则,一旦sql执行过程中出现异常,而在catch异常处理语句中没有进行rollback回滚操作,事务会一直处于等待状态,造成事务锁。
总结一下,如果数据库操作要用到事务的话(批量操作需要用事务大家都知道的吧?不然每一条数据改动都提交一次会严重影响效率,采用事务在所有数据更改完毕之后一次性提交),以下代码必不可少,且必须按顺序执行:
try { ... conn.setAutoCommit(false); ... conn.commit(); ... } catch (SQLException e) { conn.rollback(); ... } finally { conn.setAutoCommit(true); ... }
相关文章推荐
- 解决JDBC操作数据库日期类型数据时无法精确到秒的问题
- 数据库事务(1)数据库事务的特性以及 并发事务引起的问题
- 浅谈Java中数据在内存中的状态,以及String、StringBuffer、==、equals、数组等问题
- 转:浅谈Java中数据在内存中的状态,以及String、StringBuffer、==、equals、数组等问题
- php写入数据到数据库以及Mysql数据库乱码的问题
- 浅谈Java中数据在内存中的状态,以及String、StringBuffer、==、equals、数组等问题
- Redis内存使用达到maxmemory设定值后玩家数据无法写入的问题
- 浅谈Java中数据在内存中的状态,以及String、StringBuffer、==、equals、数组等问题
- android中application共享数据以及内存泄露问题
- 关于数据库自增ID数据写入问题的解决
- 解决:hibernate查询过多时与数据库连接断开或无法再查询到数据问题。
- DataTable数据批量写入数据库三种方法比较 以及方法介绍
- centOS下无法正常获取数据库表数据的问题
- SQLSERVER 占了500多M内存,原来的程序无法一次查询出50多W数据了,记录下这个问题的解决过程。
- 解决WinForm中ComboBox控件的“设置"DataSourse”属性后无法修改项集合”以及两个不相关联的ComboxBox控件实现数据列表显示不可实现的问题
- 微软企业库5.0学习笔记(三十五)数据访问模块 DataSet以及数据库事务
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值 数据库插入的数据长度过长引起无法插入数据
- mysql写入数据库后,数据出现乱码问题的解决方案
- Hibernate3不使用事务无法保存或修改数据问题
- 不当事务代码引起的数据库死锁问题