【数据库】使用Collection.setAutoCommit(false)的注意事项

来源:互联网 发布:华为网络交换机价格 编辑:程序博客网 时间:2024/06/01 18:53
  1. setAutoCommit总的来说就是保持数据的完整性,一个系统的更新操作可能要涉及多张表,需多个SQL语句进行操作  
  2.   
  3. 循环里连续的进行插入操作,如果你在开始时设置了:conn.setAutoCommit(false);  
  4. 最后才进行conn.commit(),这样你即使插入的时候报错,修改的内容也不会提交到数据库,  
  5. 而如果你没有手动的进行setAutoCommit(false);  
  6. 出错时就会造成,前几条插入,后几条没有  
  7. 会形成脏数据~~ 

  1. setAutoCommit(false)的误用  
  2. (设定setAutoCommit(false)没有在catch中进行Connection的rollBack操作,操作的表就会被锁住,造成数据库死锁):  
  3. 误用Connection.setAutoCommit导致的数据库死锁问题。  
  4. 系统在发布到用户的的服务器了,运行一段时间偶尔出现某些功能不能正常运行,甚至不能自动恢复,严重导致服务器当机,表现为服务器不响应用户的请求,数据库有大量的锁。在服务器重启后才能恢复正常。今天通遍的查看了一下代码,初步分析了原因,记录了下来,跟大家交流交流。  
  5. 先看下面一段有问题的代码:  
  6.    
  7. 1       Connection con = null;  
  8. 2      try{  
  9. 3          con = getConnection();  
  10. 4          con.setAutoCommit(false);  
  11.            /* 
  12. 5          * update USER set name=’winson’ where id=’000001’; 
  13.             */  
  14. 6          con.commit();  
  15. 7       }finally{  
  16. 8          if(con!=null){  
  17. 9              try {  
  18. 10                 con.close();  
  19. 11             } catch (SQLException e) {  
  20. 12                 e.printStackTrace();  
  21. 13             }  
  22.            }  
  23.        }  
  24. 分析:问题就出现在第4行,写代码的人把数据库连接con 设置成非自动提交,但没有在执行出现异常的时候进行回滚。如果在执行第5行的时候出现异常,con既没有提交也没有回滚,表USER就会被锁住(如果oracle数据库就是行锁),而这个锁却没有机会释放。有人会质疑,在执行con.close()的时候不会释放锁吗?因为如果应用服务器使用了数据库连接池,连接不会被断开。  
  25. 附:在oracle上查看锁的方法:select * from v$lock_object或者select * from v$lock. 

  1. 参考正确的写法应该是:  
  2.         Connection con = null;  
  3.        try{  
  4.            con = getConnection();  
  5.            con.setAutoCommit(false);  
  6.            /* 
  7.             * do what you want here. 
  8.             */  
  9.            con.commit();  
  10.         }catch(Throwable e){  
  11.            if(con!=null){  
  12.                try {  
  13.                    con.rollback();  
  14.                } catch (SQLException e1) {  
  15.                    e1.printStackTrace();  
  16.                }  
  17.            }  
  18.   
  19. throw new RuntimeException(e);  
  20.         }finally{  
  21.            if(con!=null){  
  22.                try {  
  23.                    con.close();  
  24.                } catch (SQLException e) {  
  25.                    e.printStackTrace();  
  26.                }  
  27.            }  
  28.        }  
  29.    
  30. 这种疏忽很容易出现,但又导致非常严重的运行问题。所以在这里作个提醒,以后在处理外部资源的时候一定要格外小心。今天还发现代码中一些地方滥用synchronized关键字,导致系统性能受到很大的影响,处理不当跟前面提到问题一起出现,那系统就是时候over了。  


原创粉丝点击