Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Oracle Tutorial.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
401.64 Кб
Скачать

Автономные транзакции.

Создадим две таблицы:

create table kk_ordinal_table(id number);

create table kk_autonomous_commiting_table(id number);

С использованием директивы 'PRAGMA AUTONOMOUS_TRANSACTION' напишем процедуру kk_autonomous_insert, которая будет commit-ить вставку в таблицу kk_autonomous_commiting_table, но не будет при этом commit-ить вызвавшую kk_autonomous_insert внешнюю транзакцию:

create or replace procedure kk_autonomous_insert(p_id integer) as

PRAGMA AUTONOMOUS_TRANSACTION;

begin

insert into kk_autonomous_commiting_table (id) values (p_id);

commit;

end kk_autonomous_insert;

В первой сессии выполняем сделующий блок. dbms_lock.sleep(10) - это 10 секунд безделия:

begin

dbms_lock.sleep(10);

insert into kk_ordinal_table (id) values (1);

kk_autonomous_insert(1);

dbms_lock.sleep(10);

insert into kk_ordinal_table (id) values (2);

kk_autonomous_insert(2);

dbms_lock.sleep(10);

insert into kk_ordinal_table (id) values (3);

kk_autonomous_insert(3);

commit;

end;

Во второй сессии во время выполнения вышеприведенного анонимного блока следует смотреть на то, как попадают данные в таблицы kk_ordinal_table и kk_autonomous_commiting_table. В kk_ordinal_table данные мы увидим только через 30 секунд (после commit в вызванном блоке), а в kk_autonomous_commiting_table будет появляться по одной строке каждые 10 секунд.

select * from kk_ordinal_table;

select * from kk_autonomous_commiting_table;

При желании можно сделать

truncate table kk_ordinal_table;

truncate table kk_autonomous_commiting_table;

и повторить эксперимент.

Задача. Автономное логирование этапов загрузки.

Дана таблица клиентов:

create table kk_clients_big_table(client_name varchar2(100), region_name varchar2(100), passport_ser_num varchar2(100));

Дана таблица логирования событий:

create table kk_events_log(event_date date, event_description varchar2(4000));

1) С использованием директивы 'PRAGMA AUTONOMOUS_TRANSACTION' создать процедуру kk_insert_kk_events_log(in_event_date in date default sysdate, in_event_description in varchar2) по вставке данных в kk_events_log.

2) Написать PL/SQL-блок, который заполняет данные о клиентах и логирует этапы загрузки:

2.1) Пишет в kk_events_log, что начата вставка данных об именах клиентов.

Вставляет в kk_clients_big_table 50000 случайно сгенерированных значений client_name. Поля region_name и passport_ser_num оставлять пустыми.

Пишет в kk_events_log, что завершена вставка данных об именах клиентов.

2.2) Пишет в kk_events_log, что начат update данных о регионах клиентов.

Делает update kk_clients_big_table.region_name случайными данными по всей таблице.

Пишет в kk_events_log, что завершен update данных о регионах клиентов.

2.3) Пишет в kk_events_log, что начат update данных о паспортах клиентов.

Делает update kk_clients_big_table.passport_ser_num случайными данными по всей таблице.

Пишет в kk_events_log, что завершен update данных о паспортах клиентов.

Случайные значения имен, регионов и паспортов клиентов можно брать с помощью конструкции translate(to_char(trunc(1000000 * dbms_random.value)), '1234567890', 'ABCDEFGHIJ').

3) Во время работы PL/SQL-блока в другой сессии регулярно смотреть, до какого этапа дошла загрузка, запросом из лога:

select * from kk_events_log order by event_date desc, event_description desc;

Создадим процедуру kk_insert_kk_events_log:

create or replace procedure kk_insert_kk_events_log(in_event_date in date default sysdate,

in_event_description in varchar2) as

PRAGMA AUTONOMOUS_TRANSACTION;

begin

insert into kk_events_log

(event_date, event_description)

values

(in_event_date, in_event_description);

commit;

end kk_insert_kk_events_log;

Напишем требуемый PL/SQL-блок:

begin

-- 2.1

kk_insert_kk_events_log(in_event_description => 'Начата вставка данных об именах клиентов');

for i in 1 .. 50000 loop

insert into kk_clients_big_table

(client_name)

values

(translate(to_char(trunc(1000000 * dbms_random.value)),

'1234567890',

'ABCDEFGHIJ'));

end loop;

kk_insert_kk_events_log(in_event_description => 'Завершена вставка данных об именах клиентов');

-- 2.2

kk_insert_kk_events_log(in_event_description => 'Начат update данных о регионах клиентов');

for z in (select rowid rw from kk_clients_big_table) loop

update kk_clients_big_table

set region_name = translate(to_char(trunc(1000000 * dbms_random.value)),

'1234567890',

'ABCDEFGHIJ')

where rowid = z.rw;

end loop;

kk_insert_kk_events_log(in_event_description => 'Завершен update данных о регионах клиентов');

-- 2.3

kk_insert_kk_events_log(in_event_description => 'Начат update данных о паспортах клиентов');

for z in (select rowid rw from kk_clients_big_table) loop

update kk_clients_big_table

set passport_ser_num = translate(to_char(trunc(1000000 *

dbms_random.value)),

'1234567890',

'ABCDEFGHIJ')

where rowid = z.rw;

end loop;

kk_insert_kk_events_log(in_event_description => 'Завершен update данных о паспортах клиентов');

--

commit;

end;

Согласно требованию задачи во время работы этого PL/SQL-блока в другой сессии будем регулярно смотреть, до какого этапа дошла загрузка, запросом:

select * from kk_events_log order by event_date desc, event_description desc;

Только в конце PL/SQL-блока выполняется commit, потому что, если загрузка упадет на каком-то этапе, то недогруженные данные нам не нужны. А до какого этапа дошла загрузка, можно понять из лога.

По завершении PL/SQL-блока посмотрим на загрузившиеся данные:

select * from kk_clients_big_table;

Отметим, что update-ы выполнялись медленнее, чем insert-ы. Если бы это были update-ы не по rowid и не по проиндексированным полям, то было бы еще медленнее.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]