Добавление столбца в таблицу Oracle OLTP

Я пытаюсь добавить столбец, допускающий значение NULL, в часто используемую таблицу в базе данных Oracle 10 OLTP, пока приложение работает и занято. Добавление столбца, допускающего значение NULL, — это всего лишь изменение словаря данных, и поэтому любая блокировка таблицы удерживается только в течение короткого периода времени (который может быть обработан системой).

Проблема в том, что мой ALTER TABLE часто не работает с этим:

ORA-00054: resource busy and acquire with NOWAIT specified

Мой текущий подход состоит в том, чтобы заблокировать изменение, запустив его до тех пор, пока в таблице не останется блокировок. Это означает, что я не могу полностью запустить такой скрипт в SQL*Plus, но мне нужно скопировать и вставить каждое выражение и убедиться, что оно работает.

Есть ли способ лучше?


person WW.    schedule 10.02.2011    source источник
comment
Имейте в виду, что он декомпилирует все (представления, пакеты, триггеры и т. д.), зависящее от таблицы, что может быть не так хорошо в производственной среде....   -  person cagcowboy    schedule 10.02.2011
comment
+1 за комментарий cagcowboy. Нехорошо для кода изменять таблицы в рабочей среде, потенциально много недействительных объектов. Это проблема управления изменениями, которую необходимо координировать.   -  person tbone    schedule 10.02.2011
comment
11g немного улучшил ситуацию с перекомпиляцией, с отслеживанием зависимостей на более низком уровне.   -  person Gary Myers    schedule 11.02.2011
comment
Некоторые объекты становятся недействительными и автоматически перекомпилируются при следующем использовании. Лучше, чем закрыть приложение, сделать короткую паузу. Существует не так много PL/SQL, так что это не займет много времени. Приложение обрабатывает ORA-04068: существующее состояние пакетов было отброшено.   -  person WW.    schedule 11.02.2011


Ответы (1)


Как насчет грубой силы? Поместите его в бесконечный цикл и выйдите из него, когда закончите. Псевдокод (не проверял):

create or replace 
procedure execDDL(ddl in varchar2) is
   myexp EXCEPTION;
   pragma exception_init (myexp, -54);
begin

 loop
   begin
      execute immediate ddl;
      exit;
   exception
      when myexp then 
         null;
 end loop;
 end;
person Samuel    schedule 10.02.2011
comment
+1, хотя я бы добавил вызов dbms_lock.sleep, чтобы ваш блок не монополизировал ресурсы без необходимости (короткое ожидание между двумя попытками). - person Vincent Malgrat; 10.02.2011
comment
Думаю, я мог бы сделать это, но это не кажется очень элегантным - person WW.; 11.02.2011