DeepEdit!

Программирование баз данных на Oracle, техническая документация, литература, статьи и публикации

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Перезапускаемые процессы требуют сложной логики

Наиболее серьезная проблема с подходом “фиксации перед завершением логи­ческой транзакции” заключается в том факте, что он часто оставляет вашу базу данных в неопределенном состоянии, если оператор UPDATE прерывается на пол­пути. Если только вы не позаботитесь об этом заранее, будет очень трудно переза­пустить неудавшийся процесс, и позволить ему найти место, в котором он был пре­рван. Например, предположим, что мы не применяем функцию LOWER() к столбцу, как в предыдущем примере, а некоторую другую функцию столбца, как показано ниже: 
last_ddl_time = last_ddl_time + 1; 
Если прервать цикл UPDATE на полпути, как мы сможем перезапустить его? Мы даже не сможем повторно запустить его сначала, потому что в этом случае неко­торые данные будут увеличены на 2, а другие — на 1. Если мы опять потерпим неудачу, то при следующем запуске, некоторые увеличатся на 3, другие — на 2, а остальные — на 1. Значит, нужна более сложная логика — какой-то способ “разбие­ния” данных. Например, можно обработать сначала каждое значение OBJECT_NAME, начинающееся с A, затем — с B и так далее: 
ops$tkyte@ORA10G> create table to_do
2 as
 3 select distinct substr( object_name, 1,1 ) first_char
4 from T
 5 /Table created. Таблица создана. 
ops$tkyte@ORA10G> begin

12 end;
13 /22257 rows updated
22257 строк обновлено. 
1167 rows updated
1167 строк обновлено 
135 rows updated
135 строк обновлено 
1139 rows updated
1139 строк обновлено 
2993 rows updated
2993 строк обновлено 
691 rows updated
691 строк обновлено 
... 2810 rows updated
2810 строк обновлено 
6 rows updated
6 строк обновлено 
10 rows updated
10 строк обновлено 
2849 rows updated
2849 строк обновлено 
1 rows updated
1 строка обновлена 
2 rows updated
2 строк обновлено 
7 rows updated
7 строк обновлено 
PL/SQL procedure successfully completed.
Процедура PL/SQL успешно завершена. 
Теперь мы можем перезапустить процесс, если он завершится сбоем, поскольку уже не станем обрабатывать имена объектов, которые были успешно обработаны. Проблема с этим подходом, однако, заключается в том, что если только у нас нет атрибута, позволяющего равномерно распределить данные, то мы столкнемся с очень широким распределением строк. Первому UPDATE придется выполнить на­много больше работы, чем всем прочим вместе взятым. Вдобавок если другие се­ансы обращаются к этой же таблице и модифицируют данные, они также могут обновить поле object_name. Предположим, что некоторый другой сеанс обнов­ляет объект по имени Z, переименовывая его в A, после того, как мы уже обра­ботали все объекты на A. В этом случае мы потеряем эту запись. Более того, это очень неэффективный процесс по сравнению с UPDATE T SET LAST_DDL_TIME = LAST_DDL_TIME+1. Возможно, мы воспользуемся индексом для чтения каждой строки таблицы или выполним полное сканирование n раз — и то, и другое неже­лательно. О таком подходе можно сказать очень много плохого. 
И поэтому лучший подход — первый, который описан в начале главы 1: делать это просто. Если это можно сделать на SQL — делайте это на SQL. Что невозможно сделать на SQL, делайте на PL/SQL. Делайте это, используя минимально возмож­ный объем кода. Выделяйте достаточные ресурсы. Всегда думайте о том, что может произойти в случае ошибки. Мне очень часто приходилось видеть людей, кодирую­щих циклы обновления, которые великолепно работали с тестовыми данными, но терпели крах при обработке реальных данных. Они попадали впросак, поскольку не имели понятия, где именно прервалась обработка. Намного проще выставить правильно размер сегмента отката, нежели писать перезапускаемую программу. Если у вас есть действительно большие таблицы, которые нужно обновлять, то вы должны использовать секционирование (подробнее о нем рассказывается в главе 10), которое позволит вам обновить каждую секцию индивидуально. Тогда вы мо­жете даже применять параллельный DML для выполнения обновлений. 
 









jAntivirus