您的位置:首页 > 数据库

Ibatis批处理SqlMapClient使用不关闭,资源耗尽,死锁错误!

2007-04-03 09:51 232 查看
今天做OA的及时消息通讯的---消息缓存方式实现.

因为要求缓存消息,发送到服务器的消息并不会立即持久化到数据库中,我做的是,当缓存的消息达到一定的数目的时候,启动持久化线程,进行持久化,持久化是用Ibatis写的一个方法:如下:




public void insertMEG2REV(Hashtable messagequeue, Vector receiverqueue) throws MessageErrorException, SQLException...{


SqlMapClient sqlmap=(SqlMapClient)ServiceLocator.findMyBean("sqlMapClient");






sqlmap.startBatch();


Enumeration em=messagequeue.elements();


//插入及时消息




while(em.hasMoreElements())...{


Message message=(Message)em.nextElement();


Object Key=sqlmap.insert("MessageDao.insertNewMessage3",message);




}


//插入接收信息


int REVSIZE=receiverqueue.size();




for(int i=0;i<REVSIZE;i++)...{


Receiver re=(Receiver)receiverqueue.get(i);


// System.out.println("----"+re.getMessage().getPrimaryKey()+" asa "+re.getPrimaryKey()+" "+re.getAffirmtime());


// if(re.getAffirmtime()==null)


if(re.getAffirmtime()==null)


sqlmap.insert("ReceiveDao.insertNewReceive2",re);


else


sqlmap.insert("ReceiveDao.insertNewReceive3",re);


}






sqlmap.executeBatch();






}

当持久化阀值比较小的时候,就会生成很多个持久化线程,但是他们并不是一生成就启动,而是按照生成的先后顺序来启动,这是为了保证在插入数据时,不会产生没有外键依赖的异常!一个线程接一个线程的启动,如果前面的线程,没有完成,后面的线程必须等待.这是用连表的方式实现的.

由于上面所说,当持久化线程一多,频繁启动线程,调用上面的代码,把数据插入数据库~问题来了,一般在启动100多次线程后,服务器死锁了,这个时候的症状是:CPU利用率为0(表示并不是计算量太大造成),其余任何WEB服务不能访问,除了JSP页面会很慢的响应外.其余几乎不能响应了.

如果我没猜错的话,死锁了???线程太多,但他们并没有启动啊!,不存在线程竞争资源而死锁.

后来我怀疑是批处理的代码有问题,修改如下:




public void insertMEG2REV(Hashtable messagequeue, Vector receiverqueue) throws MessageErrorException, SQLException...{


SqlMapClient sqlmap=(SqlMapClient)ServiceLocator.findMyBean("sqlMapClient");






try...{


sqlmap.startTransaction();


sqlmap.startBatch();


Enumeration em=messagequeue.elements();


//插入及时消息




while(em.hasMoreElements())...{


Message message=(Message)em.nextElement();


Object Key=sqlmap.insert("MessageDao.insertNewMessage3",message);




}


//插入接收信息


int REVSIZE=receiverqueue.size();




for(int i=0;i<REVSIZE;i++)...{


Receiver re=(Receiver)receiverqueue.get(i);


// System.out.println("----"+re.getMessage().getPrimaryKey()+" asa "+re.getPrimaryKey()+" "+re.getAffirmtime());


// if(re.getAffirmtime()==null)


if(re.getAffirmtime()==null)


sqlmap.insert("ReceiveDao.insertNewReceive2",re);


else


sqlmap.insert("ReceiveDao.insertNewReceive3",re);


}






sqlmap.executeBatch();






}catch(Exception e)...{


throw new MessageErrorException("插入消息和接收人 线程 失败--"+tools.millsTODateString(System.currentTimeMillis()));




}finally...{


sqlmap.commitTransaction();


sqlmap.endTransaction();


}




}

这次与上面的代码明显不同的是: 增加了事务的管理.在最后要结束SqlMapClient.

原来我不加事务的管理的意思是:尽可能地把数据插入数据库,如果产生异常,也不至于这次批处理完全回滚.

看来我错了,事务管理不仅仅涉及到事务的管理,还关系到数据库资源的获取的释放!

加上事务管理后,程序运行正常,不再死锁!!!!!!!!!

由此看来,并不是死锁,是因为你没有释放连接,导致数据库资源耗尽.

所以你在使用别的WEB服务,特别是需要连接数据库的WEB服务时,它取不到数据库连接,它就会等待,等待有可用的连接可以获得的时候,调用堆栈才会执行下去.这就造成了上面描述的现象:CPU利用率为0,但是却不响应,原因是它在等待数据库连接的获得,JSP页面能正常访问,原因是该JSP页面不涉及到数据库操作.所以能正常访问
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐