ORACLE Использование SERIALIZABLE в PL/SQL для загрузки согласованных данных

Для загрузки непротиворечивых данных из OLTP-базы данных выполните процедуру:

   procedure move_tables_to_mst_layer(v_sync sync_data) is
   pragma autonomous_transaction;
   v_src_table  varchar2(128);
   sql_stm      varchar2(30000);
   v_proc    varchar2(128);

begin

   execute immediate 'alter session SET ISOLATION_LEVEL = SERIALIZABLE';

   for rec in (select a_tbl_name as tblnm from a_tables
                where a_tbl_type in ('T0', 'T1')
                order by a_tbl_order
              )
   loop

       v_src_table := 'STG_'||rec.tblnm;
       sql_stm := 'insert /*+ append */ into '||v_src_table||' select t1.*
                    from '||rec.tblnm||' t1
                   where row_seq > '||v_sync.v_rowseq
                     ;
       --dbms_output.put_line(sql_stm);
       execute immediate sql_stm;
       --commit;
   end loop;

   commit;
   execute immediate 'alter session SET ISOLATION_LEVEL = READ COMMITTED';
exception
when others then
    errpck.raise_n_stop('SYNC', v_proc, 'Procedure move_tables_to_mst_layer');
end move_tables_to_mst_layer;

Версия Оракул 12с. Индикатор поля row_seq - заполняется триггером для каждой таблицы. Для любой операции DML (вставка или обновление): new.row_seq = seq_rowseq.nextavl, где seq_rowseq — глобальная последовательность. Периодически (раз в 6-12 часов) возникает ошибка external key no parent. Это означает, что процедура вставила новые записи из дочерней таблицы и не вставила новые записи из родительской таблицы - я не знаю, как это происходит. Может ли быть сериализуемый уровень изоляции с немедленным исключением?


person Igor Egorov    schedule 26.04.2020    source источник


Ответы (1)


Я не думаю, что вы предоставили достаточно информации, чтобы кто-то мог вам помочь. Каковы структуры таблиц? Другие процессы вставляются в эти таблицы? Какова связь FK между таблицами?

Еще одно замечание: вам абсолютно не следует использовать триггеры для заполнения столбца из последовательности в Oracle 12c и более поздних версиях. Триггеры — враг хорошо работающего DML, а функция IDENTITY, добавленная в 12c, сводит на нет причины их использования.

В сети уже есть хорошая документация. Мне лично нравится эта статья.

Вот простой пример использования существующей последовательности (которая у вас есть).

CREATE SEQUENCE so_61439648_seq;

CREATE TABLE so_61439648 (
 some_id NUMBER,
 data_1 VARCHAR2(100),
 data_2 VARCHAR2(100)
);

ALTER TABLE so_61439648 MODIFY some_id DEFAULT so_61439648_seq.nextval;

Вот как это настроить при создании таблицы, но с отдельной последовательностью.

CREATE SEQUENCE so_61439648_seq;

CREATE TABLE so_61439648 (
 some_id NUMBER DEFAULT so_61439648_seq.nextval,
 data_1 VARCHAR2(100),
 data_2 VARCHAR2(100)
);

Вы также можете оставить генерацию и присоединение последовательности к Oracle, но лично мне, по тем же причинам, что у вас есть красивые имена для ваших ограничений, нравится описанный выше метод, потому что он делает взаимосвязь ясной.

Вот сгенерированный Oracle метод.

CREATE TABLE so_61439648 (
 some_id NUMBER GENERATED ALWAYS AS IDENTITY,
 data_1 VARCHAR2(100),
 data_2 VARCHAR2(100)
);

SELECT t.data_default
  FROM all_tab_columns t
 WHERE t.table_name = 'SO_61439648'
   AND t.column_name = 'SOME_ID';
-- "ISEQ$$_1874517".nextval
person Kevin Seymour    schedule 13.05.2020