Từ khóa Oracle PL / SQL AUTONOMOUS_TRANSACTION
sẽ gây ra một thủ tục để tạo một phiên khác, thực hiện giao dịch, cam kết / khôi phục chỉ giao dịch riêng tư đó và trả lại quyền kiểm soát luồng cho phụ huynh.
Oh..tất cả gửi email về dữ liệu không được cam kết.
EDIT: (do chỉnh sửa bài gốc)
Gần như cùng một vấn đề phát sinh nếu bạn muốn nhập tệp từ một thư mục. Nếu bạn xóa tệp bên trong giao dịch, thì giao dịch có thể thất bại và tệp đã bị xóa nhưng không bao giờ được nhập. Hoặc bạn xóa tập tin sau khi giao dịch. Sau đó, việc xóa tệp có thể không thành công và tệp được nhập lần thứ hai.
Loại vấn đề này được gọi là a bug
.
Giải pháp là:
- Xác định mỗi bước là của riêng mình
TRANSACTION
- Bạn sẽ muốn tạo chúng theo cách mà bạn có thể chạy lại (hoặc bỏ qua) các bước khi cần thiết
- Chạy từng bước theo thứ tự thích hợp.
- không gửi email trước
COMMIT
.
- không xóa một tập tin trước khi tải dữ liệu thành công
- Bạn sẽ cần theo dõi "bạn đang ở đâu" và nếu bước đó đã qua / thất bại.
Ví dụ EMAIL
Bạn nên có một thủ tục để sendEmail
được gọi sau commit
.
Nếu bạn muốn gọi thủ tục trước đó commit
, bạn sẽ cần thêm một hàng vào hàng đợi rollback
với giao dịch chính. Đối với Oracle, đây sẽ là một trong hai Advance Queuing
hoặc góiAPEX_MAIL
Bằng cách đặt nó trong một quy trình riêng biệt, bạn có thể sendEmail
lần thứ 2 theo yêu cầu [người dùng cuối].
Xử lý tập tin
Bạn có một thuật toán chứa một vài bước trong đó mỗi bước có thể thất bại. Điều này thực sự khác với sendEmail
vấn đề của bạn .
Bạn cần ghi lại những gì bạn đang xử lý, bạn đang ở đâu trong thuật toán của mình và nếu bước đó đã thành công hay thất bại.
Để phục hồi từ một lỗi ở bất kỳ bước nào, mỗi bước của quy trình cần được xác định là rời rạc TRANSACTION
.
Trong Oracle, tôi sẽ có các thủ tục này (1 thủ tục mỗi TRANSACTION
):
create or replace
package file_processing_package
as
procedure update_file_processing_status(
p_id IN files_to_process.id%TYPE
, p_status IN process_states.id%TYPE);
function add_a_file_to_be_processed( p_filename IN files_to_process.file_name%TYPE )
return files_to_process.id%TYPE;
procedure load_data_from_file( p_id in files_to_process.id%TYPE );
procedure process_already_loaded_data( p_id in files_to_process.id%TYPE );
procedure delete_file_from_os( p_id in files_to_process.id%TYPE );
end;
/
Điều này dựa trên các bảng sau:
CREATE TABLE PROCESS_STATES (
id int generate by default on null as identity, -- 12c+
state_desc varchar2(25) not null,
constraint process_states_pk primary key (id),
constraint process_states_uq1 unique (state_desc)
);
insert into process_states( state_desc ) values ( 'file to be processed' );
insert into process_states( state_desc ) values ( 'file loaded' );
insert into process_states( state_desc ) values ( 'processing' );
insert into process_states( state_desc ) values ( 'processing failed' );
insert into process_states( state_desc ) values ( 'processing succeeded' );
insert into process_states( state_desc ) values ( 'delete failed' );
insert into process_states( state_desc ) values ( 'OK' ); -- delete succeeded
commit;
CREATE TABLE FILES_TO_PROCESS (
id int generate by default on null as identity, -- 12c+
file_name varchar2(50) not null,
process_state_id int not null,
constraint file_to_process_pk primary key (id),
constraint file_to_process_uq1 unique (file_name),
constraint file_to_process_fk1 foreign key (process_state_id)
references (process_states.id)
);
Các UNIQUE
ràng buộc về FILE_NAME
ngăn chặn cùng một tệp được xử lý hai lần.