自主交易 Oracle PL / SQL

⚡ 智能摘要

交易控制声明 Oracle PL/SQL,特别是 COMMIT、ROLLBACK 和 SAVEPOINT,决定是否保存或放弃待处理的 DML 更改。自治事务作为独立的子程序运行,其提交或回滚操作独立于主事务。

  • 💾 犯罪: 将所有待处理的 DML 更改永久化,结束事务,释放锁,并删除所有保存点。
  • ↩️ 回滚: 撤销待处理的更改,可以是整个事务,也可以撤销到指定的保存点。
  • 📌 保存点: 标记事务中的某个点,以便后续的 ROLLBACK TO 操作只能撤销部分工作。
  • 🔀 自主交易: PRAGMA AUTONOMOUS_TRANSACTION 指令允许子程序自行提交或回滚。
  • 🧾 用例: 自主事务适用于审计和错误日志记录,即使主工作回滚,这些记录也必须保留。
  • 🤖 人工智能协助: GitHub Copilot 等 AI 助手会生成 COMMIT、ROLLBACK 和 PRAGMA 代码块,并标记缺失的提交。

自主交易 Oracle PL/SQL 中的 COMMIT 和 ROLLBACK

PL/SQL 中的 TCL 语句是什么?

TCL 代表事务控制语句。这些语句用于保存或回滚待处理的事务。它们至关重要,因为除非事务被保存,否则通过 TCL 所做的更改将无法执行。 DML 语句 不会永久存储在数据库中。以下是不同的 TCL 语句。 PL / SQL.

个人陈述 描述
犯罪 保存所有待处理的交易。
回滚 放弃所有待处理的交易。
保存点 在事务中创建一个回滚点,之后可以回滚到该点。
回滚到 丢弃指定保存点之前的所有待处理事务。

在以下情况下,交易将完成:

  • 当发出上述任何语句时(SAVEPOINT 除外)。
  • 当发出 DDL 语句时(DDL 是自动提交语句)。
  • 当发出 DCL 语句时(DCL 是自动提交语句)。

使用存档点和回滚

上表介绍了 SAVEPOINT 和 ROLLBACK TO,它们结合使用,可以让你对事务进行部分控制。SAVEPOINT 标记当前事务中的一个指定点。之后对 SAVEPOINT 执行 ROLLBACK TO 操作会撤销其之后的所有更改,同时保留当前事务的原始数据。ping 之前完成的工作完好无损。

当长时间事务执行多个操作时,这非常有用。 SQL 执行多个步骤,但只有最后一步失败。与其放弃整个事务,不如回滚到上一个有效的保存点并继续。

语法:

SAVEPOINT <savepoint_name>;
   -- one or more DML statements
ROLLBACK TO <savepoint_name>;

关于存档点,需要记住的关键点:

  • 保存点仅存在于当前事务中;提交或完全回滚会删除所有保存点。
  • 回滚到某个存档点时,之后创建的所有存档点都会被删除,但回滚到的存档点会被保留。
  • ROLLBACK TO 不会结束事务;在保存点之前所做的更改将保持挂起状态,直到您执行 COMMIT 或 ROLLBACK 操作。
  • 如果重复使用存档点名称,则新的存档点会将标记移动到后面的位置。

因为 ROLLBACK TO 会使事务保持打开状态,所以你最终还是要决定是提交剩余的更改还是使用完全 ROLLBACK 来放弃它们。

什么是自治事务

在 PL/SQL 中,对数据所做的所有修改都称为一个事务。当对事​​务执行保存或丢弃操作时,事务才被视为完成。如果没有执行保存或丢弃操作,则事务不被视为完成,对数据的修改不会永久保存到服务器上。

默认情况下,PL/SQL 将会话期间的所有修改视为单个事务,保存或放弃该事务会影响会话中所有待处理的更改。而独立事务则允许开发人员在单独的事务中进行更改,并保存或放弃该特定事务,而不会影响主会话事务。

  • 可以在子程序级别指定自主事务。
  • 使任何 子程序 如果要在不同的事务中工作,则应在该代码块的声明部分中给出关键字 PRAGMA AUTONOMOUS_TRANSACTION。
  • 它指示编译器将此视为一个单独的事务,并且在此块内进行的保存或丢弃操作不会反映在主事务中。
  • 在离开此自治事务并返回主事务之前,必须发出 COMMIT 或 ROLLBACK 命令,因为任何时候只能有一个事务处于活动状态。
  • 因此,一旦启动了自主交易,就必须先保存并完成该交易,然后控制权才能转移回主交易。

语法:

DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
.
BEGIN
<execution_part>
[COMMIT|ROLLBACK]
END;
/

在上述语法中,该区块已成为一个独立的交易。

例如1: 在这个例子中,我们将了解自主交易是如何运作的。

下面的屏幕截图显示了此自主交易示例及其输出。 Oracle.

自主交易示例:在主交易回滚的同时提交嵌套区块 Oracle PL / SQL

DECLARE
   l_salary   NUMBER;
   PROCEDURE nested_block IS
   PRAGMA autonomous_transaction;
    BEGIN
     UPDATE emp
       SET salary = salary + 15000
       WHERE emp_no = 1002;
   COMMIT;
   END;
BEGIN
   SELECT salary INTO l_salary FROM emp WHERE emp_no = 1001;
   dbms_output.put_line('Before Salary of 1001 is'|| l_salary);
   SELECT salary INTO l_salary FROM emp WHERE emp_no = 1002;
   dbms_output.put_line('Before Salary of 1002 is'|| l_salary);    
   UPDATE emp 
   SET salary = salary + 5000 
   WHERE emp_no = 1001;

nested_block;
ROLLBACK;

 SELECT salary INTO  l_salary FROM emp WHERE emp_no = 1001;
 dbms_output.put_line('After Salary of 1001 is'|| l_salary);
 SELECT salary INTO l_salary FROM emp WHERE emp_no = 1002;
 dbms_output.put_line('After Salary of 1002 is '|| l_salary);
end;

输出

Before:Salary of 1001 is 15000 
Before:Salary of 1002 is 10000 
After:Salary of 1001 is 15000 
After:Salary of 1002 is 25000

Code 说明:

  • Code 第2行: 声明 l_salary 为 NUMBER 类型。
  • Code 第3行: 声明 nested_block 过程。
  • Code 第4行: 将 nested_block 过程设为 AUTONOMOUS_TRANSACTION。
  • Code 第 7-9 行: 将员工编号 1002 的工资增加 15000 美元。
  • Code 第10行: 提交自主交易。
  • Code 第 13-16 行: 打印变更前员工 1001 和 1002 的工资明细。
  • Code 第 17-19 行: 将员工编号 1001 的工资增加 5000 美元。
  • Code 第20行: 调用 nested_block 过程。
  • Code 第21行: 放弃主要交易。
  • Code 第 22-25 行: 修改后打印员工 1001 和 1002 的工资明细。

员工编号 1001 的加薪未反映在账簿中,因为主交易已被丢弃。员工编号 1002 的加薪已反映在账簿中,因为该笔交易被单独处理并保存在账簿末尾。

因此,无论主事务中是保存还是丢弃,自治事务中的更改都会被保存,而不会影响主事务。

何时使用自主交易

自主事务功能强大,因此了解何时使用它们至关重要。应将它们用于那些必须独立于主事务成功或失败的任务,而不是用于核心业务逻辑。常见用例包括:

  • 审计日志记录: 记录谁更改了敏感数据、何时更改以及旧值和新值,以便即使主事务回滚,日志也能保留下来。
  • 错误记录: 在内部写入错误记录 例外 处理程序并提交它,这样诊断详情将被保留,而失败的事务将被丢弃。
  • 计数器和统计数据: 增加一个使用计数器或点击计数,该计数必须保持不变,无论调用者的结果如何。
  • 在触发器内部提交: 触发器不能直接发出 COMMIT 请求;只有通过自主事务才能发出 COMMIT 请求。

避免将普通更新操作与主事务共享结果,而应使用独立事务。过度使用独立事务可能会将数据隐藏在独立的提交之后,从而增加调试难度。通常,每个独立事务块都必须以显式的 COMMIT 或 ROLLBACK 结束。

自主交易与常规交易

常规(主)事务和独立事务的区别在于其范围和独立性。下表对二者进行了比较。

方面 常规交易 自主交易
适用范围 分享一次会话交易 作为单独的子事务运行
提交/回滚效果 影响所有待处理的会话更改 仅影响自治模块
声明 默认行为 在声明部分中使用 PRAGMA AUTONOMOUS_TRANSACTION
父级回滚的影响 更改丢失 已承诺的自主变更将被保留
典型用途 核心业务逻辑 审计和错误日志记录

与普通人不同 嵌套块独立区块(或称自治区块)的变更始终与包含它的主交易共享结果,而自治区块则独立存在。理解这一区别有助于您判断一个区块何时应该独立,何时应该共享主交易的结果。

常见问题

Oracle 引发 ORA-06519 错误并回滚自治工作。每个自治事务都必须以显式的 COMMIT 或 ROLLBACK 结束,控制权才能返回给主事务,因为同一时间只允许一个事务处于活动状态。

不能直接执行。普通的触发器不能发出 COMMIT 或 ROLLBACK 请求。使用 PRAGMA AUTONOMOUS_TRANSACTION 声明触发器或其调用的过程,可以使其独立于触发触发器的语句提交自身的更改。

不。一旦父事务被挂起,自治事务就会独立运行,无法看到父事务未提交的更改。它只能看到数据库中已提交的数据,因此等待父事务锁可能会导致死锁。

是的。每个 DDL 语句,例如 CREATE、ALTER 或 DROP,在执行前后都会隐式地执行 COMMIT 操作。会话中任何待处理的 DML 操作都会自动提交,因此 DDL 语句之后无法回滚。

一个自治块可以调用另一个自治块,并且每个自治块都管理自己的 COMMIT 或 ROLLBACK。 Oracle 通过 TRANSACTIONS 初始化参数限制同时处于活动状态的交易数量,因此非常深的自治区块嵌套可能会失败。

不。COMMIT 操作会使更改永久生效,释放锁并删除保存点,因此无法使用 ROLLBACK 操作撤销。要撤销已提交的数据,必须运行新的 DML 操作。在提交之前,请使用 SAVEPOINT 和 ROLLBACK TO 进行部分撤销。

是的。 GitHub 副驾驶 根据注释草拟 COMMIT 和 ROLLBACK 逻辑、SAVEPOINT 块和 PRAGMA AUTONOMOUS_TRANSACTION 过程。 Rev查看提交位置和错误处理,因为提交位置错误可能会破坏事务边界。

AI助手会扫描程序,查找缺失或错位的COMMIT和ROLLBACK语句、循环内部的提交以及未关闭的独立代码块。这种机器学习审查会标记事务错误,并在代码部署到生产环境之前建议更安全的边界。

总结一下这篇文章: