Запрос висит оракул 10g
У меня есть эта странная проблема с нашим программным обеспечением.
Является на производстве в течение 5 лет, и у нас не было таких проблем...
Проблема:
У нас есть задание spring (планировщик), которое делает запрос через спящий режим, извлекает объекты и изменяет их.
Ну, это работало несколько лет, но месяц назад запрос зависает 5-10 раз в день (запрос вызывается каждые 10 минут). И когда он зависает, мы должны перезапустить службу.
Следующий код выполняет запрос:
@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
}
});
}
Источник данных определяется как это (я знаю, что это не должно быть на производстве, но это единственный способ его работы - я пытался использовать пул соединений oracle, но затем запрос зависает чаще).:
<?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>
Используемое программное обеспечение:
- spring 1.2.7
- hibernate 3.0.5
- oracle 10.2.0.1 (RAC)
- oracle jdbc 10.1.0.2
- Red Hat 3 EL
- Java 1.5_06
Что я пробовал до сих пор:
- использовать пул соединений oracle в качестве данных
источник → провалился с подвеской
соединения
- used oracle jdbc 10.2.0.5 → Я думал, что решил это... и через несколько часов он снова повесился: (
В оракуле нет блокировок базы данных, насколько я могу видеть...
В чем может быть проблема?
UPDATE:
в оракуле EM:
Результаты ADDM:
Были найдены операторы SQL, потребляющие значительное время базы данных.
Запрос потребляет значительное время базы данных. Воздействие 81%.
Пользовательский ввод/вывод ожидает 97%.
- Ответы отдельных операторов SQL
для значительного ожидания ввода-вывода пользователя были
найдено.
- Отдельные сегменты базы данных
ответственный за значительный пользовательский ввод-вывод
ожидания были найдены.
- Пропускная способность подсистемы ввода-вывода
был значительно ниже, чем
ожидается.
ОБНОВЛЕНИЕ: (15.03.2011)
В настоящее время служба работает почти 48 часов без подвешивания.
Я скептически отношусь к тому, что это решит проблему, но я внес некоторые изменения в код:
Удалены функции decode(delivered,null,0,1) = 0
и decode(" + sqlCustAlias + ".deleteDate,null,1,0) = 1
в запросе и заменены их операторами is null
.
Поставляемое поле индексируется, но индексирование не может использоваться в функциях decode
.
Считаете ли вы, что это просто совпадение?
ОБНОВЛЕНИЕ: (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сек.!
Ответы
Ответ 1
Во-первых, когда этот запрос зависает, проверьте V $SESSION_WAIT, чтобы узнать, что ожидает сеанс.
Второе наблюдение: код, показанный выше, игнорирует параметр max
, если параметр benefitType
не равен нулю. Это намеренно? Возможно ли, что запрос "висит" только в том случае, когда параметр availType имеет значение 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, и, если возможно, соответствующий идентификатор сеанса и какое событие он ожидает. Вы должны иметь возможность использовать текст SQL для определения интересующего вас сеанса.