2011-03-12 20 views
13

Tengo este extraño problema con nuestro software. Es está en producción durante 5 años y no hemos tenido este tipo de problemas ...consulta cuelga oráculo 10g

Problema:

Tenemos un trabajo de muelle (programador) que hace una consulta a través de hibernación, recupera los objetos y los modifica.

Bueno, esto funcionó durante varios años, pero hace un mes la consulta se cuelga 5-10 veces al día (la consulta se invoca cada 10 minutos). Y cuando se cuelga, tenemos que reiniciar el servicio.

El siguiente código hace la consulta:

@SuppressWarnings("unchecked") 
public List<Delivery> 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 
     } 
    }); 
} 

Fuente de datos se define como esto (sé que esto no se supone que es en la producción, pero esta es la única forma en que funciona - He intentado utilizar Oracle agrupación de conexiones, pero luego la consulta cuelga más a menudo ..):

<?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> 
    <beans> 
     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close"> 
     <property name="driverClassName" value="${jdbc.driverClassName}" /> 
     <property name="url" value="${jdbc.url}" /> 
     <property name="username" value="${jdbc.username}" /> 
     <property name="password" value="${jdbc.password}" /> 
     <property name="connectionProperties"> 
     <props> 
      <prop key="tcp.nodelay">yes</prop> 
      <prop key="delayRowPrefetch">20</prop> 
      <prop key="defaultBatchSize">5</prop> 
     </props> 
     </property> 
     </bean> 
    </beans> 

Software utilizado:

  • primavera 1.2.7
  • hibernación 3.0.5
  • Oracle 10.2.0.1 (RAC)
  • JDBC de Oracle 10.1.0.2
  • Red Hat 3 EL
  • Java 1.5_06

lo que he tratado de manera ahora:

  • uso conjunto de conexiones de datos Oracle como fuente -> fracasaron con colgar conexiones
  • utilizado JDBC de Oracle 10.2.0.5 -> pensé He resuelto que ... y después de unas horas se cuelguen de nuevo :(

No hay cerraduras de bases de datos Oracle en la medida de lo posible ver ...

¿Cuál podría ser el problema?

ACTUALIZACIÓN:

en el oráculo EM:

hallazgos ADDM: sentencias SQL que consumen tiempo importante base de datos se han encontrado. La consulta consume un tiempo de base de datos significativo. Impacto 81%. E/S de usuario espera 97%.

  • sentencias SQL individuales responsables para el usuario significativo de E/S de espera eran encontrado.
  • Segmentos de base de datos individuales responsables de la E/S de usuario significativo espera fueron encontrados.
  • Se esperaba que el rendimiento del subsistema de E/S fuera significativamente menor que .

ACTUALIZACIÓN: (15.03.2011)

Por ahora el servicio funciona para casi 48 horas sin colgar.

soy escéptico de que esto va a resolver el problema, sino que lo hicieron algunos cambios en el código:

retira el decode(delivered,null,0,1) = 0 y decode(" + sqlCustAlias + ".deleteDate,null,1,0) = 1 funciones de consulta y los reemplazó con is null declaraciones.
El campo entregado está indexado, pero la indexación no se puede usar en las funciones decode.

¿Crees que esto es solo una coincidencia?

ACTUALIZACIÓN: (16.03.2011)

alert.log muestra ahora muchas entradas como esta:

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 

Parece ser desde 3 días antes de las sesiones de 232.624 segundos ..!

+5

+1 porque obviamente está trabajando el fin de semana para resolver un problema de producción. No hay horas extras en nuestra profesión, pero al menos hay un par de representantes :-) – corsiKa

+0

muchas gracias. Los fines de semana están reservados para EMCY :-) – alesko

+4

Mi experiencia ha sido que si algo estaba funcionando, pero ahora no lo es, es solo porque algo cambió. Este código no ha cambiado, lo que significa que sus datos probablemente sí lo hayan hecho. Ahora, conozco tanto sobre hibernación como esa roca de allí, así que no puedo analizar el código para encontrar el problema muy bien, pero analizaría lo que podría haber cambiado con los datos. Por supuesto, ya has superado eso, estoy seguro ... pero * encogerse de hombros * solo vale la pena mencionarlo. – corsiKa

Respuesta

3

En primer lugar, cuando se bloquea esta consulta, compruebe V $ SESSION_WAIT para ver qué espera la sesión.

Segunda observación: El código que ha mostrado arriba parece ignorar el parámetro max a menos que el parámetro benefitType no sea nulo. Es esto intencional? ¿Es posible que la consulta se "cuelgue" solo cuando el parámetro benefitType es nulo?

Lo siento, supuse que tenía alguna forma de identificar la sesión correcta dentro de Oracle. Pruebe con una consulta como esta:

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; 

que mostrará todo el SQL se está ejecutando actualmente, y si es posible la identificación de sesión relacionados y qué evento se está a la espera de. Debería poder usar el texto SQL para identificar la sesión que le interesa.

+0

Lo comprobaré tan pronto como vuelva a suceder. Esto no debería tomar mucho tiempo. – alesko

+0

Y para ser claros, verifique algunas veces y vea si el evento de espera cambia o si cambia el número de secuencia. Incluso si está esperando el mismo evento pero el número de secuencia cambia, eso significa que está trabajando, solo que muy lentamente. –

+0

La pregunta es ¿cómo saber qué sesión es la que cuelga? Hay más de 16 sesiones con el evento "SQL * Net message from/to client". – alesko

Cuestiones relacionadas