Das Oracle PL / SQL-Schlüsselwort AUTONOMOUS_TRANSACTION
bewirkt, dass eine Prozedur eine weitere Sitzung erstellt, eine Transaktion ausführt, nur diese private Transaktion festschreibt / zurücksetzt und die Flusskontrolle an das übergeordnete Element zurückgibt.
Oh ... senden Sie niemals E-Mails mit nicht festgeschriebenen Daten.
BEARBEITEN: (aufgrund der Bearbeitung des ursprünglichen Beitrags)
Etwa das gleiche Problem tritt auf, wenn Sie Dateien aus einem Verzeichnis importieren möchten. Wenn Sie die Datei innerhalb der Transaktion löschen, schlägt die Transaktion möglicherweise fehl und die Datei wurde gelöscht, aber nie importiert. Oder Sie löschen die Datei nach der Transaktion. Dann schlägt das Löschen der Datei möglicherweise fehl und die Datei wird ein zweites Mal importiert.
Diese Art von Problem wird als a bezeichnet bug
.
Die Lösung ist:
- Definieren Sie jeden Schritt als seinen eigenen
TRANSACTION
- Sie möchten sie so erstellen, dass Sie die Schritte nach Bedarf erneut ausführen (oder überspringen) können
- Führen Sie jeden Schritt in der entsprechenden Reihenfolge aus.
- Senden Sie keine E-Mails vor
COMMIT
.
- Löschen Sie keine Datei vor dem erfolgreichen Laden der Daten
- Sie müssen nachverfolgen, wo Sie sich gerade befinden und ob dieser Schritt erfolgreich war oder nicht.
E-MAIL-Beispiel
Sie sollten eine Prozedur haben, nach sendEmail
der aufgerufen werden sollte commit
.
Wenn Sie die Prozedur vorher aufrufen möchten commit
, müssen Sie einer Warteschlange, die rollback
die Haupttransaktion enthält , eine Zeile hinzufügen . Für Oracle ist dies entweder Advance Queuing
oder das PaketAPEX_MAIL
Wenn Sie es in ein separates Verfahren einfügen, können Sie es sendEmail
auf Anfrage des [Endbenutzers] ein zweites Mal tun.
Datei verarbeiten
Sie haben einen Algorithmus, der einige Schritte enthält, bei denen jeder Schritt fehlschlagen kann. Das ist eigentlich anders als dein sendEmail
Problem.
Sie müssen aufzeichnen, was Sie verarbeiten, wo Sie sich in Ihrem Algorithmus befinden und ob dieser Schritt erfolgreich war oder fehlgeschlagen ist.
Um einen Fehler in einem beliebigen Schritt zu beheben, muss jeder Schritt des Prozesses als diskret definiert werden TRANSACTION
.
In Oracle hätte ich folgende Prozeduren (1 Prozedur pro 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;
/
Dies basiert auf den folgenden Tabellen:
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)
);
Die UNIQUE
Einschränkung für FILE_NAME
verhindert, dass dieselbe Datei zweimal verarbeitet wird.