查询挂起oracle 10g

我的软件有这个奇怪的问题。 是生产了5年,我们没有这样的问题……

问题:

我们有一个spring job(scheduler),它通过hibernate进行查询,检索对象并修改它们。

好吧,这工作了几年,但一个月前查询每天挂起5-10次(每10分钟调用一次查询)。 当它挂起时,我们必须重新启动服务。

以下代码执行查询:

@SuppressWarnings("unchecked") public List findScheduledForDelivery(final String inType, final int max, final String benefitType ) { //getHibernateTemplate().clear(); return getHibernateTemplate().executeFind(new HibernateCallback() { public Object doInHibernate(Session session) throws SQLException { Criteria criteria = session.createCriteria(Delivery.class); criteria.createAlias("reward","r"); criteria.createAlias("r.customer","c"); criteria.createAlias("c.inNe","i"); criteria.createAlias("r.promotion","p"); criteria.createAlias("benefit","b"); String sqlCustAlias = StringHelper.generateAlias("c", 2); criteria.add(Expression.disjunction() .add(Expression.eq("inStatus", INStatus.InterfaceFailure)) .add(Expression.eq("inStatus",INStatus.Initial))); criteria.add(Expression.le("deliverAt", new Date())); String dateString = "2000/01/01"; DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); Date startDate = new Date(); try { startDate = dateFormat.parse(dateString); criteria.add(Expression.ge("deliverAt", startDate)); } catch(ParseException e) { e.printStackTrace(); } String sqlEqual = "decode(delivered,null,0,1) = 0"; criteria.add(Expression.sql(sqlEqual)); sqlEqual = "decode(" + sqlCustAlias + ".deleteDate,null,1,0) = 1"; criteria.add(Expression.sql(sqlEqual)); if(inType != null ) { for(INType i : INType.values()) if(i.toString().equals(inType)) { criteria.add(Expression.eq("i.inType", i)); break; } } criteria.add(Expression.eq("p.active", true)); if(benefitType != null) { if(benefitType.equals("FREECREDIT")) criteria.add(Expression.disjunction() .add(Expression.eq("b.type", BenefitType.FREE_CREDIT)) .add(Expression.eq("b.type", BenefitType.FREE_CREDIT_FTAM))); else if(benefitType.equals("NONFREECREDIT")) { criteria.add(Expression.conjunction() .add(Expression.ne("b.type", BenefitType.FREE_CREDIT)) .add(Expression.ne("b.type", BenefitType.OTHER)) .add(Expression.ne("b.type", BenefitType.VOUCHER))); criteria.add(Expression.isNull("b.md3Profile")); } if(max != 0) criteria.setMaxResults(max); } criteria.addOrder( Order.desc("p.priority") ); criteria.addOrder( Order.asc("deliverAt") ); return criteria.list(); <===== hangs here } }); } 

数据源被定义为这个(我知道这不应该是生产,但这是它的唯一工作方式 – 我试图使用oracle连接池,但随后查询挂起更频繁……):

           yes 20 5     

使用的软件:

  • spring1.2.7
  • hibernate 3.0.5
  • oracle 10.2.0.1(RAC)
  • oracle jdbc 10.1.0.2
  • 红帽3 EL
  • Java 1.5_06

到目前为止我尝试了什么:

  • 使用oracle连接池作为数据源 – >挂起连接失败
  • 用过oracle jdbc 10.2.0.5 – >我以为我已经解决了……几个小时之后它又被绞死了:(

我可以看到oracle上没有数据库锁…

可能是什么问题呢?

更新:

在oracle EM:

ADDM调查结果:发现消耗大量数据库时间的SQL语句。 该查询占用大量数据库时间。 影响81%。 用户I / O等待97%。

  • 找到了负责重要用户I / O等待的单个SQL语句。
  • 找到了负责重要用户I / O等待的各个数据库段。
  • I / O子系统的吞吐量明显低于预期。

更新:(15.03.2011)

目前,该服务工作了近48小时,没有挂起。

我怀疑这会解决问题,但我对代码做了一些更改:

在查询中删除了decode(delivered,null,0,1) = 0 decode(" + sqlCustAlias + ".deleteDate,null,1,0) = 1 decode(delivered,null,0,1) = 0decode(" + sqlCustAlias + ".deleteDate,null,1,0) = 1函数,并将它们替换为is null语句。
传递的字段已编制索引,但索引不能用于decodefunction。

你认为这只是巧合吗?

更新:(16.03.2011)

alert.log现在显示许多条目,如下所示:

 ORA-01555 caused by SQL statement below (SQL ID: affkpm4j7azc4, Query Duration=232624 sec, SCN: 0x0003.dca70559): Tue Mar 15 17:43:06 2011 select * from ( select this_.id as id5_, this_.deliverAt as deliverAt68_5_, this_.delivered as delivered68_5_, this_.inDelivery as inDelivery68_5_, this_.lastDeliveryTry as lastDeli5_68_5_, this_.tries as tries68_5_, this_.sentAt as sentAt68_5_, this_.sent as sent68_5_, this_.retry as retry68_5_, this_.inStatus as inStatus68_5_, this_.errorMessage as errorMe11_68_5_, this_.inCvsDelivery as inCvsDe12_68_5_, this_.cvsDelivered as cvsDeli13_68_5_, this_.cvsLastDeliveryTry as cvsLast14_68_5_, this_.cvsTries as cvsTries68_5_, this_.collectedPoints as collect16_68_5_, this_.smsMessage as smsMessage68_5_, this_.inOldStatus as inOldSt18_68_5_, this_.replacedDate as replace19_68_5_, this_.oldMsisdn as oldMsisdn68_5_, this_.deletedDate as deleted21_68_5_, this_.addManualDate as addManu22_68_5_, this_.stornoPromiseDate as stornoP23_68_5_, this_.stornoINDate as stornoI24_68_5_, this_.activationCode as activat25_68_5_, this_.activationExpirationDate as activat26_68_5_, this_.rewardId as rewardId68_5_, this_.benefitId as b 

它似乎是3天前的会议.. 232624秒!

首先,当此查询挂起时,请检查V $ SESSION_WAIT以查看会话正在等待的内容。

第二个观察:除非benefitType参数为非null,否则上面显示的代码似乎忽略了max参数。 这是故意的吗? 仅当benefitType参数为null时,查询是否可能“挂起”?

对不起,我以为你有办法在Oracle中识别正确的会话。 尝试这样的查询:

 select v2.sid, v2.module, substr(v1.sql_text,1,180) sql_text, v1.rows_processed, v2.event, v2.seq# from v$sqlarea v1, v$session v2 where v1.users_executing > 0 and v2.sql_address (+) = v1.address; 

这将显示当前正在执行的所有SQL,如果可能,还会显示相关的会话ID以及它正在等待的事件。 您应该能够使用SQL文本来标识您感兴趣的会话。