dbms_utility.format_error_backtrace - отслеживание ошибок в pl/sql

Статьи про Oracle -> Программирование

dbms_utility.format_error_backtrace - отслеживание ошибок в pl/sql

v:1.0 03.12.2011
Петрелевич Сергей

Часто при обработке исключений в pl/sql разработчики ограничиваются использованием встроенной функции sqlerrm, однако в Oracle есть и другие интересные средства для обработки ошибок. Одно из этих средств - функция dbms_utility.format_error_backtrace.

Функция dbms_utility.format_error_backtrace возвращает список вызовов функций и процедур от места генерации исключения до места его обработки.
Для рассмотрения работы dbms_utility.format_error_backtrace создадим тестовый пакет с процедурами, которые подобно матрешкам вызываются одна из другой.

create or replace package Err as

 procedure testProc1;
 procedure testProc2;
 procedure testProc3;
 procedure testProc4;

end;

Пример 1. dbms_utility.format_error_backtrace в каждом обработчике исключений

В первом примере функция dbms_utility.format_error_backtrace вставлена в обработчики исключений каждой процедуры.

  1. create or replace package body Err as
  2.  
  3. procedure testProc1 is
  4. begin
  5.  dbms_output.put_line('testProc1');
  6.  testProc2;
  7. exception
  8. when others then
  9.  dbms_output.put_line('testProc1 error:'||dbms_utility.format_error_stack);
  10.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  11. end;
  12.  
  13. procedure testProc2 is
  14. begin
  15.  dbms_output.put_line('testProc2');
  16.  testProc3;
  17. exception
  18. when others then
  19.  dbms_output.put_line('testProc2 error:'||dbms_utility.format_error_stack);
  20.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  21.  raise;
  22. end;
  23. procedure testProc3 is
  24. begin
  25.  dbms_output.put_line('testProc3');
  26.  testProc4;
  27. exception
  28. when others then
  29.  dbms_output.put_line('testProc3 error:'||dbms_utility.format_error_stack);
  30.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  31.  raise;
  32. end;
  33.  
  34. procedure testProc4 is
  35. begin
  36.  dbms_output.put_line('testProc4');
  37. raise no_data_found;
  38. exception
  39. when others then
  40.  dbms_output.put_line('testProc4 error:'||dbms_utility.format_error_stack);
  41.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  42.  raise;
  43. end;
  44.  
  45. end;
Выполняем первую процедуру.
begin
 err.testProc1;
end;

Получаем результат:
testProc1
testProc2
testProc3
testProc4
testProc4 error:ORA-01403: no data found

stack:ORA-06512: at "DEV.ERR", line 38

testProc3 error:ORA-01403: no data found

stack:ORA-06512: at "DEV.ERR", line 43
ORA-06512: at "DEV.ERR", line 27

testProc2 error:ORA-01403: no data found

stack:ORA-06512: at "DEV.ERR", line 32
ORA-06512: at "DEV.ERR", line 16

testProc1 error:ORA-01403: no data found

stack:ORA-06512: at "DEV.ERR", line 21
ORA-06512: at "DEV.ERR", line 6
Видно, что функция dbms_utility.format_error_backtrace выводит пакет, в котором сработало исключение и номер строки. Надо отметить, что в данном примере и строки вида dbms_output.put_line('testProc3 error:'||dbms_utility.format_error_stack); отлично формируют стек ошибки, dbms_utility.format_error_backtrace лишь уточняет конкретную строку.

Пример 2. dbms_utility.format_error_backtrace в стартовой процедуре, во всех процедурах есть обработчики исключений

Рассмотрим другой пример.
На этот раз dbms_utility.format_error_backtrace будет в стартовой процедуре, из которой вызываются другие. В других процедурах будут обработчики исключений, но в них не будет вызова dbms_utility.format_error_backtrace.

  1. create or replace package body Err as
  2.  
  3. procedure testProc1 is
  4. begin
  5.  dbms_output.put_line('testProc1');
  6.  testProc2;
  7. exception
  8. when others then
  9.  dbms_output.put_line('testProc1 error:'||dbms_utility.format_error_stack);
  10.  dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  11. end;
  12.  
  13. procedure testProc2 is
  14. begin
  15.  dbms_output.put_line('testProc2');
  16.  testProc3;
  17. exception
  18. when others then
  19.  raise;
  20. end;
  21. procedure testProc3 is
  22. begin
  23.  dbms_output.put_line('testProc3');
  24.  testProc4;
  25. exception
  26. when others then
  27.  raise;
  28. end;
  29.  
  30. procedure testProc4 is
  31. begin
  32.  dbms_output.put_line('testProc4');
  33.  raise no_data_found;
  34. exception
  35. when others then
  36.  raise;
  37. end;
  38.  
  39. end;
Выполняем первую процедуру.
begin
 err.testProc1;
end;

Получаем результат:
testProc1
testProc2
testProc3
testProc4
testProc1 error:ORA-01403: no data found

stack:ORA-06512: at "DEV.ERR", line 19
ORA-06512: at "DEV.ERR", line 6
Информации не очень-то много. Складывается впечатление, что ошибка возникла в 19 строке кода, хотя правильное место - строка 34. Причина в том, что dbms_utility.format_error_backtrace показывает стек не с места фактического появления ошибки, а с мест ее последнего перехвата. В нашем случае это процедура proc2, строка 21.
Получается, в этом случае dbms_utility.format_error_backtrace ни только не помогает, а еще и мешает, запутывает следы.

Пример 3. dbms_utility.format_error_backtrace в стартовой процедуре, в других процедурах нет обработчиков исключений

На этот раз все исключения обрабатываются только в одном месте - вызывающей функции, и только в ней используется dbms_utility.format_error_backtrace.

  1. create or replace package body Err as
  2.  
  3. procedure testProc1 is
  4. begin
  5.  dbms_output.put_line('testProc1');
  6.  testProc2;
  7. exception
  8.  when others then
  9.   dbms_output.put_line('testProc1 error:'||dbms_utility.format_error_stack);
  10.   dbms_output.put_line('stack:'||dbms_utility.format_error_backtrace);
  11. end;
  12.  
  13. procedure testProc2 is
  14. begin
  15.  dbms_output.put_line('testProc2');
  16.  testProc3;
  17. end;
  18.  
  19. procedure testProc3 is
  20. begin
  21.  dbms_output.put_line('testProc3'); 
  22.  testProc4; 
  23. end;
  24.  
  25. procedure testProc4 is
  26. begin
  27.  dbms_output.put_line('testProc4'); 
  28.  raise no_data_found;
  29. end;
  30.  
  31. end;
Выполняем первую процедуру.
begin
 err.testProc1;
end;

Получаем результат:
testProc1
testProc2
testProc3
testProc4
testProc1 error:ORA-01403: no data found

stack:ORA-06512: at "DEV.ERR", line 32
ORA-06512: at "DEV.ERR", line 25
ORA-06512: at "DEV.ERR", line 18
ORA-06512: at "DEV.ERR", line 7
На этот раз информации куда больше. По выводу функции dbms_utility.format_error_backtrace можно точно отследить, что ошибка появилась в функции testProc4, строка 32, и какие процедуры выполнялись.

Из этих примеров можно вывести две основные тактики применения dbms_utility.format_error_backtrace.
Эту функцию надо вставлять в каждый обработчик исключений или обрабатывать все исключения в одной точке - стартовой процедуре(функции).

Метки: PL/SQL  

Комментарии.

Внимание.
Комментировать могут только зарегистрированные пользователи.
Возможно использование следующих HTML тегов: <a>, <b>, <i>, <br>.