非事务保存操作的术语

gue*_*tli 7 terminology

如果你只看数据库,一切都很好。您有事务,如果出现问题,一切都会回滚。这很好 - 我喜欢这个。

但是:我想发送邮件。现在我遇到了麻烦,因为我无法回滚。

例子:

  1. 交易开始
  2. 邮件被发送
  3. 其他事情完成(在 DB 内)
  4. 出了点问题。
  5. 回滚。

如何解决这个问题是另一个问题,而不是这个问题。

这个问题一般怎么称呼这个。在这个例子中是关于发送邮件。但是,一旦您在事务边界之外的系统中修改某些内容,就会出现同样的问题。

这个问题名字吗?

如果您想从目录中导入文件,大致会出现同样的问题。如果您删除事务内的文件,则事务可能会失败并且文件被删除但从未导入。或者您在交易后删除该文件。然后文件的删除可能会失败,并且该文件会再次导入。

我不想为此重新发明解决方案。这就是为什么我需要这个问题的匹配项。然后我可以阅读一些论文,了解什么是 2018 年的“最新技术”。

Mic*_*utz 6

Oracle PL/SQL 关键字AUTONOMOUS_TRANSACTION将导致过程创建另一个会话、执行事务、提交/回滚该私有事务,并将流控制返回给父级。

哦..永远不要就未提交的数据发送电子邮件。

编辑:(由于对原始帖子的编辑)

如果您想从目录中导入文件,大致会出现同样的问题。如果您删除事务内的文件,则事务可能会失败并且文件被删除但从未导入。或者您在交易后删除该文件。然后文件的删除可能会失败,并且该文件会再次导入。

这种类型的问题称为bug.

解决办法是:

  • 将每个步骤定义为自己的 TRANSACTION
    • 您将希望以一种可以根据需要重新运行(或跳过)步骤的方式创建它们
  • 按适当的顺序运行每个步骤。
    • 之前不要发送电子邮件COMMIT
    • 在成功加载数据之前不要删除文件
  • 您需要跟踪“您所在的位置”以及该步骤是否通过/失败。

电子邮件示例

你应该有一个sendEmail应该在之后调用的过程commit

如果您想在 之前调用该过程commit,则需要将一行添加到将rollback包含主事务的队列中。对于 Oracle,这将是Advance Queuing或包APEX_MAIL

通过将其放在单独的程序中,您可以sendEmail根据 [最终用户的] 请求进行第二次。

进程文件

您有一个包含几个步骤的算法,其中每个步骤都可能失败。这实际上与您的sendEmail问题不同。

您需要记录您正在处理的内容、您在算法中所处的位置以及该步骤是成功还是失败。

为了从任何步骤的错误中恢复,过程的每个步骤都需要定义为一个离散的TRANSACTION

在 Oracle 中,我会有这些程序(每个程序 1 个程序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;
/
Run Code Online (Sandbox Code Playgroud)

这是基于下表:

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)
);
Run Code Online (Sandbox Code Playgroud)

UNIQUE约束FILE_NAME防止同一文件被处理两次。


mus*_*cio 1

您正在描述分布式事务。请注意,术语“事务”比简单的“数据库事务”具有更一般的含义。

在分布式事务中,不同的成员可能具有不同的 ACID 属性(例如,不一定保证电子邮件能够送达)、实现这些属性的不同方法以及不同的故障场景。

为了确保分布式事务的一致性,通常采用称为事务协调器(或管理器)的外部实体来控制每个成员(也可以称为资源或资源管理器)的提交。一种常见的方法是两阶段提交(2PC)。

如果您在互联网上搜索“分布式系统的一致性”,您会发现有关该主题的大量材料。