Форум программистов, компьютерный форум, киберфорум
Oracle
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
1184 / 540 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
1

Поймать остановку выполнения скрипта

24.10.2014, 23:18. Показов 1175. Ответов 1
Метки нет (Все метки)

Есть пакет с процедурой, в процедуре есть следующий код:
Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  PROCEDURE X(...)
  BEGIN
    LOOP
      l_id := ...;
      EXIT WHEN 
           ...
           BEGIN
                  SAVEPOINT START_POINT;
                  LOG_MSG('OK');
                  COMMIT;
           EXCEPTION
              WHEN OTHERS THEN
              BEGIN
                   LOG_MSG('XXX');
                  ROLLBACK TO START_POINT;
                  dbms_output.put_line('in process for ID : ' || id);
          
                  UPDATE buffer
                        SET STATE = 'e'
                  WHERE id = l_id;
                  dbms_output.put_line('cnt e = ' || sql%rowcount);
                  
                  dbms_output.put_line('still processing');
          
                  UPDATE journal
                        SET note = 'rolled back'
                    WHERE id = l_id
                        AND note = 'OK';          
                   dbms_output.put_line('cnt ok = ' || sql%rowcount);
                  COMMIT;
                  RAISE;
               END;
           END;
      l_finished := l_finished + 1;
    END LOOP;
    LOG_MSG('YYY');
  
  EXCEPTION
    WHEN OTHERS THEN
      LOG_MSG('ZZZ');
      RAISE;
    
  END X;
Тоесть в случае проблем в коде мы попадаем сначала в exception блок для цикла где откатываемся к точке после чего выводим сообщение XXX, обрабатываем буфер и бросаем снова исключение, его ловит обработчик и выводит ZZZ после чего выбрасывает исключение дальше.

Проблема в том что нужно чтобы всё это выполнялось даже если юзер затребовал остановку выполнения процедуры, по какой-то волшебной причине раньше так и было, но на текущий момент всё работает примерно так:
1) Если в коде произошло исключение: в output попадает XXX и ZZZ так как исключение прошло первый обработчик (внутри цикла) и второй и всё хорошо.
2) Если пользователь затребовал отмену то отрабатывает лишь кусочек первого блока перехвата исключений, тоесть выполняеться rollback, выводиться сообщение XXX и всё .... даже то что дальше идёт с выводом count'ов не отрабатывает из первого же обработчика.
Почему так может быть и как с этим бороться ?

Добавлено через 6 часов 59 минут
Прочитал что нужно ловить специальный эксепшн и when others его ловить не должно, поэтому на текущий момент теперь у меня два вопроса:
1) Какой же это when others если он не ловит некоторые исключения
2) Что вообще происходит: я вижу как начинает работать обработчик исключения так как выполняеться ролбек и выводиться сообщение в output, но остальной кусок обработчика не выполняется!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.10.2014, 23:18
Ответы с готовыми решениями:

отключить остановку выполнения через 30 секунд
Доброго всем времени суток! Мой скрипт проверяет содержимое страниц с различных сайтов (порядка...

Опция компилятора, позволяющая временно отключить остановку выполнения программы, запущенной из IDE
нет опции компилятора , чтобы временно отключить остановку выполнения программы в запущенной из...

Результат выполнения программы в консоли пропадает после выполнения скрипта
нужно отпарсить файл , но мне надо видеть что выводит сценарий , иначе мне его неотладить....

Перехват выполнения скрипта
Недавно начал заниматься реализацией перехвата функций dll. (на примерах с MessageBox, в интернете...

1
1184 / 540 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
26.10.2014, 21:32  [ТС] 2
Изучил проблему методом тыка и пришёл к выводам что user cancelled operation это очень странное исключение с очень странной обработкой запрещающее делать dml операции, продемонстрирую на примере который можно пощупать.
1) Создаём таблицу под логи и процедуру с автономной транзакцией.
Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE auto_log
(
       val VARCHAR(20)
);
CREATE OR REPLACE PROCEDURE autonomus_log (x VARCHAR2)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
  dbms_output.put_line ('auto call start');
  INSERT INTO auto_log VALUES(x);
        COMMIT;
        dbms_output.put_line ('auto call end');
END;
Наш испытуемый блок:
Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
BEGIN
  BEGIN
                BEGIN
                        BEGIN
                                BEGIN
                                  SAVEPOINT START_TEST; 
                                  INSERT INTO auto_log VALUES ('START OUR TEST');
                                        dbms_lock.sleep(seconds => 30);
                                        INSERT INTO auto_log VALUES ('END OUR TEST');
                                        
                                        EXCEPTION
                                          --все 3 сообщения будут выведены
                                                WHEN OTHERS THEN
                                                  dbms_output.put_line('start log 5');
                                                        dbms_output.put_line('start log 52');
                                                        dbms_output.put_line('start log 53');
                                                        RAISE;
                                END;
                                EXCEPTION
                                  --автономная транзакция будет начата но на инсерте оракл её срубит
                                        --поэтому сообщение о конце выполнения автономной транзакции мы не увидим
                                        WHEN OTHERS THEN
                                          autonomus_log('start log 4');
                                                RAISE;
                        END;
                        EXCEPTION
                                WHEN OTHERS THEN
                                  -- инсерт оракл срубит сразу же
                                        INSERT INTO auto_log VALUES('start log 3');
                COMMIT;
                                        RAISE;
                END;
                EXCEPTION
                        WHEN OTHERS THEN
                          -- COMMIT / ROLLBACK будет обрабатываться успешно
                                -- слип будет отбиватьсz до его завершения
                          COMMIT; -- выполнит комит нашего первого инсерта (START OUR TEST)
                                dbms_output.put_line('start log 2');
                                dbms_lock.sleep(seconds => 2);
                                dbms_output.put_line('end log 2');
                                RAISE;
        END;
        EXCEPTION
        WHEN OTHERS THEN
          --слип всегда отбиваеться, даже если промежуток времени очень короткий
                --всё что после него в текущем обработчике игнориуеться
                dbms_output.put_line('start log 1');
                dbms_lock.sleep(seconds => 1);
                dbms_output.put_line('end log 1');
                RAISE;
END;
Из этого бока видно что даже автономные транзакции не будут выполняться до конца, при этом это определённо не из-за того что оракл очень спешит завершить работу процедуры так как время работы такого блока примерно 7 секунд (если отбить на первой секунду), а время работы такого блока:
Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
BEGIN
  BEGIN
                BEGIN
                        BEGIN
                                BEGIN
                                  SAVEPOINT START_TEST; 
                                  INSERT INTO auto_log VALUES ('START OUR TEST');
                                        dbms_lock.sleep(seconds => 30);
                                        INSERT INTO auto_log VALUES ('END OUR TEST');
                                        
                                        EXCEPTION
                                                WHEN OTHERS THEN
                                                dbms_lock.sleep(seconds => 100500);
                                                RAISE;
                                END;
                                EXCEPTION
                                        WHEN OTHERS THEN
                                          dbms_lock.sleep(seconds => 100500);
                                                RAISE;
                        END;
                        EXCEPTION
                                WHEN OTHERS THEN
                                  dbms_lock.sleep(seconds => 100500);
                                        RAISE;
                END;
                EXCEPTION
                        WHEN OTHERS THEN
                          dbms_lock.sleep(seconds => 100500);
                                RAISE;
        END;
        EXCEPTION
        WHEN OTHERS THEN
          dbms_lock.sleep(seconds => 100500);
                RAISE;
END;
18 секунд (тоже если отбить на первой секунде). Из этого можно сделать выводы что оракл даёт примерно по 3 секунды на обработку каждого из блоков исключений, при этом блок обработки завершаеться если пытаеться сделать dml операцию.

Одно лишь мне остаёться непонятно: в старой версии одной из моей процедур мой логгер в автономной транзакции, если отбить выполнение процедуры, успевал писать в лог "user cancelled current operation", как это получалось я всё ещё не понимаю ...

Добавлено через 32 минуты
Методом экспериментов определил что иногда (иногда!) если срубить выполнение моей процедуры с паралельным выполнением на immediate sql то, если повезёт, оно таки доберёться до конца автономной транзакции и поэтому в логах окажеться сообщение что юзер запросил отмену выполнения. Прямой зависимости между "отмена immediate кода" и "выполнение автономной транзакции до конца" не нашёл.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.10.2014, 21:32

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Время выполнения скрипта
Здравствуйте! Пишу фреймворк для своих нужд, больше для опыта. Так вот хотел бы поинтересоваться...

Скорость выполнения скрипта
Добрый день, есть небольшой скрапт на php который распознает капчу, примерно с 90%-ым совподением ...

Время выполнения скрипта
Мне нужно каким то образом увеличить время работы скрипта, нашел пару способов, ни один не...

Последовательность выполнения скрипта
Здравствуйте! Нужен скрипт, который вначале перемещает картинку в корзину, а после открывается...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.