Как избежать максимальной ошибки open_cursor превышен при использовании Class :: DBI - PullRequest
0 голосов
/ 28 октября 2009

(Обновление для ответа на вопрос Джонатана Леффлера ниже):

Мы используем Perl 5.8.7 и Oracle 11.1.0.7.0.

В соответствии с политикой компании, разработчики не имеют произвольного контроля над обновлением программного обеспечения. Для подачи предложения высшему руководству требуются месяцы (если оно будет одобрено) - я полагаю, что это не удивительно странная ситуация и для некоторых других компаний.

Я унаследовал программу от кого-то еще, покинувшего компанию, и обнаружил предупреждение о «выдаче отката () ...» из файла журнала приложения. Фактическая проблема "максимальное превышение open_cursor" была обнаружена после того, как я запустил DBI_TRACE = 2 = / tmp / trace.log имя_программы.pl .

Глядя на число $ dbh -> {ActiveKids}, $ dbh -> {Kids} и $ dbh -> {CachedKids}, я предполагаю, что максимальный открытый курсор равен 50, так как ошибка возникает после того, как она достигает 50.


Наши устаревшие производственные коды используют следующие модули:

  • DBI - 1,48
  • Има :: DBI - 0,33
  • Класс :: DBI - 0,96
  • Класс :: DBI :: Oracle - 0,51
  • DBD :: Oracle - 1.16

По какой-то странной причине, обновление модуля до более новой версии невозможно: (

Приложение использует CDBI для обработки отношений с большим количеством таблиц. Ниже приведен упрощенный фрагмент кода:

JOB:
foreach my $job (@jobs) {
  my @records = $job->record; 

  RECORD: 
  foreach my $record (@records) {
      my @datas = $record->data;

      DATA:
      foreach my $data (@datas) {
          ....
      }
  }
}

, где каждый @ jobs , $ record и $ data - это объект таблицы, а внутренний внутренний цикл вызывает несколько других триггеров.

Где-то после нескольких циклов я получаю ошибку Oracle: максимум open_cursor превысил , а затем я получил ошибку от CDBI: выдача rollback () для дескриптора базы данных DESTROYE'd без явного отсоединять .

Я могу обойти это, undef -ing DBI CachedKids в самом внешнем цикле, с:

# somewhere during initialization
$self->{_this_dbh} = __PACKAGE__->db_Main();

....

JOB:
foreach my $job (@jobs) {
    RECORD: ....
        DATA: ....

    $self->{_this_dbh}->{CachedKids} = undef;
}

Это правильный способ сделать это?

Или CDBI поддерживает способ очистки обработчика операторов так же, как DBI $ sth-> finish () ?

Спасибо.

1 Ответ

2 голосов
/ 28 октября 2009

В какой-то момент вам придется объяснить, почему вы не можете перейти на более текущие версии программного обеспечения. Вы не упомянули, какую версию Perl вы используете или какую версию Oracle; почему-то я подозреваю, что это не 5.10.1 и не 11gR2.

Текущие версии:

  • Класс :: DBI 3.0.17
  • Класс :: DBI :: Oracle 0.51
  • DBI 1.609 (версия 1.48 от 2005 года)
  • DBD :: Oracle 1.23 (версия 1.16 с 2004 года)
  • Има :: DBI 0,35

Что изменилось недавно? Почему вы вдруг обнаруживаете проблемы в программном обеспечении, которое, по-видимому, очень стабильно? Это новый код?

В обычном DBI, когда вы отменяете дескриптор оператора (например, выводя его из области видимости), связанные с ним ресурсы высвобождаются - более или менее шумно. Однако между Class :: DBI и DBI достаточно инфраструктуры, поэтому трудно сказать, как это может отображаться.

  • Вы выяснили, каково ограничение на открытые курсоры?
  • Вы выяснили, достаточно ли вы открыли курсоров, чтобы фактически превысить этот предел?
  • Вы пытались запустить с установленным в среде DBI_TRACE? Значение, такое как 3, расскажет вам достаточно о том, что происходит, может быть, слишком много Было бы показано, правильно ли освобождаются курсоры.
  • Вы пытались уменьшить количество таблиц, обрабатываемых за один сеанс?
  • Рассматривали ли вы отключение и повторное подключение между управляющими таблицами?
  • Есть ли способ получить дескриптор оператора, соответствующий абстракциям Class :: DBI, чтобы вы могли фактически выполнить $ sth-> finish ()?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...