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页面不涉及到数据库操作.所以能正常访问
因为要求缓存消息,发送到服务器的消息并不会立即持久化到数据库中,我做的是,当缓存的消息达到一定的数目的时候,启动持久化线程,进行持久化,持久化是用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页面不涉及到数据库操作.所以能正常访问
相关文章推荐
- [转载]使用HttpWebRequest进行请求时发生错误:基础连接已关闭,发送时发生错误处理
- 【JAVA】使用JAVA7增强的try语句关闭资源(疯狂Java程序员的基本修养8.1)
- 接收对 http://192.168.1.18:8001/ObtainData/Service 的 HTTP 响应时发生错误。这可能是由于服务终结点绑定未使用 HTTP 协议造成的。这还可能是由于服务器中止了 HTTP 请求上下文(可能由于服务关闭)所致。
- SpringFramework中SqlMapClientTemplate的使用
- 在window XP下使用vsphere client 5.5 访问vCenter 或者 ESXi5.5 连接错误
- 操作必须使用一个可更新的查询;HTTP 500 - 内部服务器错误; 您未被授权查看该页;您不具备使用所提供的凭据查看该目录或页的权限;HTTP 错误 401.3 - 访问被资源 ACL 拒绝
- ES使用org.elasticsearch.client.transport.NoNodeAvailableException: No node available 错误解决方法
- 客户端在浏览网站时收到“HTTP 403.4 - 禁止访问:需要使用 SSL 查看该资源”错误,但是网站没有配置为使用 SSL
- 如何使用ResourceManger,及使用ResourceManager过程中出错的找不到资源的错误
- 解决在使用client object model的时候报“object does not belong to a list”错误
- 使用 jstack 查询线程死锁错误日志 定位问题
- [转帖]win7下计划任务schtasks使用详解及"错误:无法加载列资源"的解决方法
- 解决在Win7下使用schtasks命令显示 “错误:无法加载列表资源” 的问题
- 使用多线程方法实现一个死锁程序,用来提醒自己不要犯这样的错误
- com.ibatis.sqlmap.client.SqlMapException 错误
- 使用SmtpClient发邮件时,返回“不允许使用邮箱名称”和 “邮箱不可用”的错误信息
- C# 最基本的涉及模式(单例模式) C#种死锁:事务(进程 ID 112)与另一个进程被死锁在 锁 | 通信缓冲区 资源上,并且已被选作死锁牺牲品。请重新运行该事务,解决方案: C#关闭应用程序时如何关闭子线程 C#中 ThreadStart和ParameterizedThreadStart区别
- 解决 内部服务器错误 请求的资源在使用中