自主交易 Oracle PL / SQL
⚡ 智能摘要
交易控制声明 Oracle PL/SQL,特别是 COMMIT、ROLLBACK 和 SAVEPOINT,决定是否保存或放弃待处理的 DML 更改。自治事务作为独立的子程序运行,其提交或回滚操作独立于主事务。
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.
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 |
| 父级回滚的影响 | 更改丢失 | 已承诺的自主变更将被保留 |
| 典型用途 | 核心业务逻辑 | 审计和错误日志记录 |
与普通人不同 嵌套块独立区块(或称自治区块)的变更始终与包含它的主交易共享结果,而自治区块则独立存在。理解这一区别有助于您判断一个区块何时应该独立,何时应该共享主交易的结果。


