Не сме сами, част 3
Един малко по-добър вариант изглежда така:
– В началото вземаме текущата дата
– Когато избираме кои данни да обработим, освен processed=0 гледаме и датата на зареждане – да е по-малка от датата за начало на обработката, която се запомнили
– когато изтриваме обработените данни от loader таблицата, отново изтриваме само тези, които са „заредени“ преди началото на обработката
Процедурата би изглеждала така:
create or replace procedure Process_New_Data2 is
-- example code - has a BUG!!!
transfer_date date;
begin
-- get the time when we start the transfer
transfer_date := sysdate;
-- process the loaded batches
insert /*+append*/
into prod_table
select -- do some processing
batch_id, get_something(column1, column2), calculate_something(column3, column4),
RANK() over(PARTITION BY column5, column6 order by column7) rn,
column8, column9, ...
from loader_table
where batch_id in (select batch_id
from batch_log
where load_time < transfer_date -- get only the batches loaded before we start
and processed = 0);
-- delete the rows from loader table
delete from loader_table
where batch_id in (select batch_id
from batch_log
where load_time < transfer_date -- delete only the batches loaded before we start
and processed = 0);
-- mark the batches as processed
update batch_log
set processed = 1
where load_time < transfer_date -- mark only the batches loaded before we start
and processed = 0;
commit;
end;
За съжаление това отново не е гарантирано решение. Шанса за загуба на данни тук е много по-малък, но не е нулев, и много зависи от метода на зареждане на нови данни.
Проблема се изразявана едно ниво по-дълбоко: някоя сесия може да е заредила данни преди няколко секунди (може и минути), но да не е commit-нала промените. Съответно нашият inser-select няма да ги хване, но докато върви той, другата сесия има достатъчно време да направи commit и няколко милиона реда да се появят за малко, докато delete-а не ги изтрие безславно.
Sorry, the comment form is closed at this time.