Oracle数据库事务概述
事务介绍事务是包含一个或多个 SQL 语句的逻辑的、 原子的工作单元。事务将 SQL 语句分组以便它们可以一起被提交即将其应用到数据库或者一起被回滚即将其从数据库中撤消。Oracle 数据库将为每个事务分配一个称为事务 ID 的唯一标识符。使用事务是数据库管理系统有别于文件系统的最重要方式之一。事务的ACID特性所有 Oracle 事务都符合称为 ACID 属性的数据库事务的基本属性。ACID是以下的缩写原子性事务中的所有任务要么全部执行要么都不执行。不存在部分完成的事务。例如如果事务启动并欲更新 100 行但在系统在完成 20行更新后出现故障则数据库会回滚这 20 行更新。一致性事务会将数据库从一个一致状态变为另一个一致状态。例如 从一个储蓄账户借记、并从一个账户贷记的银行事务中故障一定不能导致数据库仅仅贷记一个账户这会导致数据不一致。隔离性一个事务必须在被提交之后其它事务才能看见其效果。例如正在更新 hr.employees 表的一个用户不会看到由另一个用户在employees 表上未提交的更改。因此对这些用户来说这些事务好像是串行执行的。持久性已提交的事务所做的更改是永久性的。事务完成后数据库通过其恢复机制确保在事务中所做的更改不会丢失。示例帐户借贷事务为了说明事务的概念考虑一个银行数据库。当一个客户将钱从储蓄账户转移到支票帐户时事务必须由三个单独的操作组成减少储蓄账户余额增加支票账户余额在事务日志中记录这笔交易Oracle 数据库必须考虑两种情况。如果所有三个 SQL 语句都对该账号维持了正确的余额则事务的效果可以应用到数据库中。但是如果某个问题如资金不足、帐号无效、或硬件故障阻止了事务中某些语句的完成则数据库必须回滚整个事务以便所有帐户的余额是正确的。下图说明了银行事务。第一条语句从储蓄帐户 3209 中减去 500 美元。第二条语句向支票帐户 3208 增加 500 美元。第三条语句在日志表中插入这笔转账记录。最后一个语句提交事务。事务的结构数据库事务由一个或多个语句组成。具体而言事务包含下列之一1、一个或多个数据操作语言 (DML) 语句一起构成的、对数据库的一个原子更改2、一个数据定义语言 (DDL) 语句3、事务有一个开始点和结束点事务的开始事务开始于所遇到的第一个可执行 SQL 语句。可执行的 SQL 语句是能产生数据库实例调用的 SQL 语句包括 DML 和 DDL 语句及 SET TRANSACTION 语句。当事务开始时 Oracle 数据库将为事务分配一个可用的撤销数据段以记录新事务的撤消条目。数据库在第一个 DML 语句过程中首先会分配撤销段和事务表槽然后分配事务 ID。事务 ID 对于事务来说是唯一的并由撤销段号、 槽号、和序列号来表示。示例下面的示例执行一个 UPDATE 语句以开始一个事务并从V$TRANSACTION 查询有关事务的详细信息 SQL UPDATE hr.employees SET salarysalary; 107 rows updated. SELECT XID AS txn_id, XIDUSN AS undo_seg, XIDSLOT AS slot, XIDSQN AS seq, STATUS AS txn_status FROM V$TRANSACTION; txn_id undo_seg slot seq txn_status ---------------- ---------- ---------- ---------- ---------------- 0600060037000000 6 6 5 ACTIVE事务的结束事务在出现以下操作时结束1、用户在没有 SAVEPOINT 子句的语句中发出 COMMIT 或ROLLBACK。提交意味着用户会显式或隐式地请求事务中所做的更改被持久化。只有在提交事务之后事务所做的更改才是永久性的并对其他用户可见。2、用户运行一个 DDL 命令如 CREATE、DROP、RENAME、或ALTER 等。数据库在每个 DDL 语句之前和之后发出一个隐式的 COMMIT 语句。如果当前事务中包含 DML 语句则 Oracle 数据库首先提交该事务然后将该 DDL 语句作为一个新的单语句事务来运行并提交。3、用户从大多数 Oracle 数据库实用程序和工具正常退出导致当前事务被隐式提交。当用户断开连接时的提交行为依赖于应用程序并且是可配置的。在程序终止之前应用程序应始终显式地提交或回滚其事务。4、客户端进程异常终止导致数据库使用存储在事务表和撤销段中的元数据来隐式回滚其事务一个事务结束后, 下一个可执行的 SQL 语句将自动启动后续事务。示例下面的示例执行一个更新来启动一个事务并以一个 ROLLBACK 语句来结束事务然后又执行一个更新启动一个新事务 注意事务 Id 变化 UPDATE hr.employees SET salarysalary; 107 rows updated. SQL SELECT XID, STATUS FROM V$TRANSACTION; XID STATUS ---------------- ---------------- 0800090033000000 ACTIVE SQL ROLLBACK; Rollback complete. SQL SELECT XID FROM V$TRANSACTION; no rows selected SQL UPDATE hr.employees SET last_namelast_name; 107 rows updated. SQL SELECT XID, STATUS FROM V$TRANSACTION; XID STATUS ---------------- ---------------- 0900050033000000 ACTIVE 第一个事务ID:0800090033000000 第二个事务ID:0900050033000000语句级原子性Oracle 数据库支持语句级原子性这意味着 SQL 语句是一个原子工作单元要么完全成功要么完全失败。成功的语句不同于已提交事务。如果一个 SQL 语句能被数据库正确分析并作为一个原子单位来运行且未产生错误且所有行都被正确更改则这个SQL 语句是成功执行的。如果 SQL 语句在执行过程中导致错误则它是不成功的该语句中的所有影响都将被回滚。此操作是一个语句级回滚。此操作具有以下特征1、未成功的 SQL 语句只会导致它本身执行的工作丢失。未成功的语句不会导致丢失当前事务中该语句之前的任何工作。例如如果前面章节的图中第二个 UPDATE 语句的执行导致错误并被回滚但由第一个 UPDATE 语句执行的工作是不会被回滚的。第一个UPDATE 语句可以由用户显式提交或回滚。2、回滚的效果是好像该语句从来未运行过。原子语句的副作用被视为原子语句的一部分例如由语句执行所引发的触发器调用。作为原子语句的一部分所产生的所有工作要么都成功要么都失败。由错误导致语句级回滚的一个示例是尝试插入重复的主键。死锁中的某个为争用相同数据的 SQL 语句也会导致语句级回滚。然而在解析中发现的错误比如语法错误实际上尚未运行因此不会导致语句级回滚系统更改号 SCNsSCN重要特征1、系统更改号 (SCN) 是一个由 Oracle 数据库使用的逻辑、 内部的时间戳。2、SCN 用于对数据库内发生的事件进行排序这是满足事务 ACID 特性的必要条件。3、Oracle 数据库使用 SCN 来标记某个位置在其之前的所有更改都被认为已写到磁盘上以避免在恢复过程中应用不必要的重做。4、数据库还使用 SCN 来标记某组数据不再存在重做的位置不完全恢复的点以便恢复过程可以在该点停止止。5、SCN 是按单调递增的顺序发生的。6、Oracle 数据库可以像使用时钟一样使用SCN因为一个 SCN 观察值指示一个逻辑时间点而其重复观察值相比之前会相同或更大。若一个事件的 SCN 比另一个事件的 SCN 低则它在数据库中发生在一个更早的时间。几个事件可以共享相同的 SCN 这意味着他们在数据库中同时发生。7、每个事务都有一个 SCN。例如如果事务更新了一行则数据库记录此更新发生时的 SCN。此事务中其他修改具有相同的 SCN。当事务提交时数据库将为此提交记录一个 SCN。8、Oracle 数据库在系统全局区SGA中递增 SCN。当事务修改数据时数据库会将一个新的 SCN 写入分配给该事务的撤销数据段。随后日志写入进程会立即将该事务的提交记录写入在线重做日志。该提交记录包含该事务的唯一 SCN。Oracle 数据库还将 SCN 用作其实例恢复和介质恢复机制的一部分。事务控制概述事务控制即管理 DML 语句所做的更改和将 DML 语句分组为事务。一般情况下应用程序设计人员都关注事务控制以便工作能按逻辑单元来完成且数据能保持一致。事务控制涉及使用下面的语句1、COMMIT 语句结束当前事务并使在事务中执行的所有更改都具有持久性。提交还会清除在事务中的所有保存点并释放事务锁。2、ROLLBACK 语句将取消当前事务中所做的工作它导致所有自上次提交或回滚以来的数据更改被丢弃。ROLLBACK TO SAVEPOINT 语句将撤消自上次保存点以来所做的更改但不会结束整个事务。3、SAVEPOINT 语句标识在事务中您可以稍后回滚到的点。事务名称事务名称是一个由用户指定的可选标记作为工作中正在执行的事务中的一个提示。使用 SET TRANSACTION … NAME 语句来为事务命名如果要用它则它必须是事务的第一个语句。示例SET TRANSACTION NAME sal_update; SET TRANSACTION NAME sal_update2;手工指定事务名称的优点1、有助于监测长时间运行的事务并解决可疑的分布式事务。2、可以在应用程序中查看事务名称及其相应事务 ID。例如数据库管理员可以在监视系统活动时在 Oracle 企业管理器 企业管理器中查看事务名称。3、数据库将事务名称写入事务的审计重做记录因此可以使用LogMiner 来搜索在重做日志中的特定事务。4、可以使用事务名称在 V$TRANSACTION 之类的数据字典视图中查找特定的事务。活动事务活动事务即是已开始但尚未提交或回滚的事务。在事务提交或回滚之前事务对数据所做的更改是暂时的。在事务结束之前数据的状态如下所示1、Oracle 数据库已在系统全局区SGA中生成撤消数据信息。撤消数据包含由事务中的 SQL 语句所更改的数据旧值。2、Oracle 数据库已在 SGA 的联机重做日志缓冲区中生成了重做信息。重做日志记录包含数据块和撤消块的更改。3、已经对 SGA 中的数据库缓冲区进行了更改。已提交事务所做的数据更改存储在 SGA 的数据库缓冲区中但不一定会立即由数据库写入器写入数据文件。磁盘写入可能会在提交之前或之后发生。4、数据更改所影响的行已被锁定。其他用户不能更改受影响的行中的数据也不能查看未提交的更改。请参阅锁定行为总结。保存点保存点是事务上下文中的一个由用户声明的中间标记。在内部此标记将被解析为一个 SCN。保存点将长事务划分为多个更小的部分。如果你在一个长事务中使用保存点就可以在之后将事务中执行的工作回滚到某个保存点之前。因此如果出了错不需要重新提交所有每个语句。回滚到保存点在未提交事务中回滚到某个保存点意味着该指定的保存点之后所做的任何更改都将被撤消但它并不意味着事务本身的回滚。当一个事务回滚到一个保存点时例如 ROLLBACK TO SAVEPOINT after_banda_sal将执行以下操作1 、Oracle 数据库将只回滚在该保存点之后运行的语句。2 、Oracle 数据库保留在 ROLLBACK TO SAVEPOINT 语句中指定的保存点但随后的所有保存点都将丢失。3 、Oracle 数据库释放在指定保存点之后获取的所有表锁和行锁但保留在该保存点之前获取的所有数据锁。事务仍处于活动状态并可以继续。注意事项排队事务取决于当时的场景之前在等待被锁定资源的事务在回滚到保存点后可能仍处于阻塞状态。一个事务被另一个事务阻塞时它会在阻塞事务后面排队因此整个阻塞事务必须提交或回滚被阻塞的事务才能得以继续。事务回滚未提交事务的回滚将撤消已由事务中的 SQL 语句执行过的任何数据更改。事务回滚后事务中所做工作的影响就不再存在。对未引用任何保存点的整个事务的回滚 Oracle 数据库执行下列操作1、通过使用相应的撤销段撤消事务中所有 SQL 语句所做的所有更改每个活动事务的事务表条目包含一个指向该事务的所有撤消数据与应用顺序相反的指针。数据库从撤销段中读取数据反转其操作然后将撤消条目标记为已应用。因此如果一个事务插入行则其回滚删除行。如果一个事务更新行则其回滚反转这个更新。如果一个事务删除一个行则其回滚重新插入该行。2、释放由事务持有的所有数据锁3、清除在事务中的所有保存点注意事项回滚的持续时间与被修改的数据量成正比。事务提交提交结束当前事务并使事务中执行的所有更改持久化。当一个事务提交时将发生以下操作1、为提交生成系统更改号 (SCN)。在关联的回滚表空间的内部事务表中记录已提交的事务。分配相应的唯一事务 SCN并将其记录在事务表中。2、日志写入器 LGWR进程将重做日志缓冲区中的剩余重做日志条目写入到在线重做日志中并将事务 SCN 写入到在线重做日志中。这个原子事件是提交事务的本质所在。3、Oracle 数据库释放在行和表上持有的锁。还在排队等待由未提交事务持有的锁的用户现在可以继续他们的工作了。4、Oracle 数据库删除保存点。5、Oracle 数据库执行一个提交清理。如果包含已提交的事务的被修改数据块仍处于 SGA 中也没有其他会话正在对他们进行修改则数据库从该块中删除与锁相关的事务信息。理想情况下COMMIT 会清理该数据块以便后续的 SELECT操作不必再执行此任务。注意由于数据块清理会生成重做所以查询可能生成重做并因此导致在下一个检查点期间该数据块会被写入。6、Oracle 数据库将事务标记为完成事务提交后用户可以查看所做的更改。通常提交是一个快速的操作而与事务大小无关。提交的速度不会随着在事务中修改的数据的大小的增大而增加。提交的最长部分是由 LGWR 执行的物理磁盘 I/O。然而LGWR 所用的时间量却减少了因为它一直在在后台以增量方式写出重做日志缓冲区中的内容。默认行为是 LGWR 必须将重做数据同步地写入联机重做日志而事务必须等到被缓冲的重做数据被写到磁盘上之后提交操作才能返回到用户。但是为取得更低的事务提交延迟应用程序开发人员可以指定重做被异步写入以便事务不需要等待重做被写入磁盘就可以立即从 COMMIT 调用返回。自治事务概述自治事务是一个独立的事务可以从另一个称为主事务的事务中调用。你可以挂起调用事务、 在自治事务中执行 SQL 操作并提交或回滚它们然后继续执行调用事务。自治事务对于那些必须独立执行、而不管调用事务是否提交或回滚的操作非常有用。例如在股票购买事务中你想要总是提交客户数据而无论是否股票购买最终成功通过。或者您想要将错误消息记录到一个调试表即使整个事务被回滚。自治事务具有以下特征1、自治事务不会看见在主事务中所做的未提交更改也不与主事务共享锁或资源。2、自治事务中的更改在其提交后对其它事务是可见的。因此用户可以立刻访问更新的信息而不必等到主事务提交。3、自治事务可以启动其他自治事务。没有关于自治事务能调用多少级别的任何限制这只受限于可用的资源。在 PL/SQL 中 自治事务在一个标有AUTONOMOUS_TRANSACTION的编译指令例程所在的自治范围内执行。在这种上下文中例程包括顶层匿名PL/SQL 块、 PL/SQL 子程序、和触发器。一个编译指令是指示编译器执行某个编译选项的指令。AUTONOMOUS_TRANSACTION 编译指令指示数据库当此过程执行时作为一个独立于其父事务的新的自治事务来执行。下图显示了控制如何从主程序 MT流向一个自治例程又如何返回。主程序是 proc1 自治例程是 proc2。自治例程在控制返回主例程之前可以提交多个事务 AT1 和 AT2。当进入一个自治例程的可执行部分时主例程将挂起。当退出自治例程时主例程就恢复了。在上图中proc1 内的提交将持久化自己的工作及在其会话中执行的任何未结工作。在 proc2 中的提交仅持久化在 proc2 事务中执行的工作。在事务 AT1 和 AT2 中的 COMMIT 语句对 MT 事务没有影响。分布式事务概述分布式数据库是在分布式系统中可以对应用程序而言作为单一数据源出现的一组数据库多个数据库。分布式事务包括一个或多个使用称为数据库链接的模式对象的语句更新位于分布式数据库中两个或更多不同节点上的数据。数据库链接dblink描述一个数据库实例如何登录到另一个数据库实例的方式。与本地数据库上的事务不同分布式事务修改了多个数据库上的数据这些修改必须以整个事务来提交或回滚。分布式事务处理更复杂因为数据库必须进行协调以将事务中所做的更改作为一个原子单元提交或回滚。Oracle 数据库必须通过网络协调事务控制并保持数据的一致性即使发生网络或系统故障。两阶段提交两阶段提交机制保证参与分布式事务的所有数据库要么都提交、或者要么都回滚事务中的语句。该机制还可以保护由完整性约束、 远程过程调用、和触发器执行的隐式 DML。在涉及多个数据库的两阶段提交中由某个数据库协调该分布式事务。发起的节点称为全局协调者。协调者询问其他数据库是否已准备好提交。如果任何数据库响应说未准备好则整个事务回滚。如果所有数据库都说已准备好则协调者将广播一个消息使该提交在每个数据库上持久化。两阶段提交机制对发出分布式事务的用户是透明的。事实上用户甚至不需要知道事务是分布式的。表示事务结束的 COMMIT 语句自动触发两阶段提交机制。在数据库应用程序正文中不需要额外编码或复杂的语句语法来包括分布式事务。Oracle数据库两阶段提交说明1、协调者与参与者 协调者负责发起和协调事务提交的数据库节点。 参与者参与分布式事务的数据库节点。 2、通信协议 Oracle两阶段提交使用TCP/IP协议进行通信确保消息的可靠传输。 3. 阶段划分 准备阶段 协调者发送准备指令给参与者。 参与者执行预提交操作并将结果返回给协调者。 协调者收集所有参与者的响应决定是否继续提交。 提交/回滚阶段 如果所有参与者都响应成功协调者发送提交指令给参与者。 参与者执行提交操作。 如果有参与者响应失败协调者发送回滚指令给参与者。 参与者执行回滚操作。 4. 防止死锁 Oracle两阶段提交通过锁定协调者和参与者的资源避免死锁的发生。可疑事务可疑分布式事务发生在两阶段提交被任何类型的系统或网络故障中断时。例如两个数据库向协调数据库报告他们已准备提交但协调数据库实例收到消息后却立即失效了。这两个准备提交的数据库现在被挂起而他们还在等待通知结果。两种解决方案1、恢复 (RECO) 后台进程会自动解决可疑分布式事务的残局。该故障修复和通信重新建立后在所有涉及到的节点上每个本地的 Oracle 数据库的RECO 进程一致地自动提交或回退任何可疑的分布式事务。2、对于长时间失败的情况 Oracle 数据库使每个本地管理员手动提交或回滚任何由于失败引起的可疑分布式事务。此选项使本地数据库管理员能够释放任何由于长期的失败所引起的无限期持有资源锁定。如果数据库必须恢复到过去的某个时间则数据库恢复工具使得在其它站点的数据库管理员能将其数据库返回到某个过去的时间点。此操作可确保全局数据库保持一致。