2013-04-15 3 views
1

Я работаю над написанием хранимой процедуры в Oracle, которая обновит таблицу, содержащую денормализованные данные. Контур процедуры:Oracle Atomic Stored Procedure

CREATE OR REPLACE PROCEDURE loadDenormalizedTable IS 
BEGIN 

DELETE FROM denormalizedTable; 

INSERT INTO 
    denormalizedTable 
    (
     data 
    ) 
SELECT DISTINCT 
    data 
FROM 
    normalizedTables; 

END; 
/

Я хочу, чтобы все это произошло в сделке, так что всегда будут данные в таблице. В настоящий момент пробелы удаления и таблица пуста в течение нескольких минут, пока вставка не будет завершена. Каков наилучший способ справиться с этим обновлением таблицы без какого-либо времени простоя?

+1

Устранение не будет видно другим сеансам до тех пор, пока вы не зафиксируете его, что вы не должны делать внутри процедуры. Итак, вы увидите пустую таблицу, но никто другой не будет. Является ли это значительно сокращенной версией вашей реальной процедуры? Также ... вы заново изобретаете [материализованные представления] (http://docs.oracle.com/cd/E11882_01/server.112/e25789/schemaob.htm#CFAIGHFC)? –

+0

Спасибо! Проблема с сеансом меня подстегнула. Теперь я вижу, что данные все еще видны приложению во время обновления таблицы. Вырезано, что я удалил все фактические таблицы и столбцы и просто добавил заполнителей. Однако структура такая же. Да, это переосмысление материализованных представлений, архитекторы данных не являются поклонниками MV. – wshato

+0

Что не так с видом на коврик? он может быть обновлен атомарно или неатомно. И после его создания вся эта работа может быть сведена до одного оператора обновления. Я не буду говорить, что я думаю о ваших данных «архитекторы» – tbone

ответ

1

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

Примечание: транзакция может охватывать несколько блоков, и блок может содержать несколько операций.

С вашего кода как указано, никакая другая сессия не будет видеть ваше удаления или вставку, пока вы не зафиксируете после вызова процедуры. Если вы просто запустить его из SQL * Plus запросит например:

SQL> exec loadDenormalizedTable; 

PL/SQL procedure successfully completed. 

SQL> 

... то кто-то другой смотрит на стол еще будут видеть старые данные, даже после того, как удаления и вставки завершена. (Любой, кто пытается выполнить процедуру, или вставляет или удаляет данные в denormalizedTable, блокирует, но предположительно вы ожидаете, что другие будут запрашивать его). Как только вы выберете commit, тогда все увидят то же самое.

Единственный способ получить поведение, вы можете описать это вручную завершить сделку в рамках процедуры:

CREATE OR REPLACE PROCEDURE loadDenormalizedTable IS 
BEGIN 

DELETE FROM denormalizedTable; 

COMMIT WORK; -- makes the delete visible elsewhere 

INSERT INTO 
    denormalizedTable 
    (
     data 
    ) 
SELECT DISTINCT 
    data 
FROM 
    normalizedTables;  
END; 
/

Вам не не нужно commit в середине процедуры, и это очень редко, что вы было бы или должно когда-либо хотеть это сделать, поскольку оно нарушает атомарность.

Возможно, вы делаете что-то, что делает неявное совершение, если вы не осознаете его; возможно, вызывая другую процедуру или функцию, которая выполняет свою собственную фиксацию (одна из причин этого не делать - она ​​может иметь неожиданные побочные эффекты!) или, возможно, заявление DDL, которое всегда будет выполнять неявное совершение за кулисами, но вы 'd должен делать это с динамическим SQL в любом случае.

Еще одна вероятность того, что вы на самом деле не делаете delete, но что вы делаете truncate. Это будет видно всем остальным немедленно, без явного фиксации, как намечено на in the documentation. Это также было бы значительным отходом от схемы, которую вы предоставили.

+0

Я все еще привык к тому, как работают сессии в Oracle. Он работает точно так, как вы описали. Благодарю. – wshato

1

Если доступна опция разбиения на Oracle, лучшим и наиболее эффективным способом сделать это является использование операции переключения разделов. Это очень распространенная операция, выполняемая во многих массивных хранилищах данных.

Смотрите некоторые примеры по адресу:

http://www.akadia.com/services/ora_exchange_partition.html http://gerardnico.com/wiki/database/oracle/partition_exchange_loading

Например, вы можете представить себе вторую таблицу с точно такой же структурой, как denormalizedTable. Чтобы реализовать операцию загрузки:

  • усечение denormalizedTable2
  • вставить данные в denormalizeTable2
  • Обменяйте разбиение таблиц denormalizedTable и denormalizedTable2

Это обычно гарантирует минимальное воздействие на запущенном приложении.

+0

Спасибо. Я буду помнить об этом, если администраторы баз данных предпочтут усечение и удаление. – wshato