
各位看官老爷大家好,今天我们书接上回,继续了解一些关于数据库事务处理的简单概念
Oracle 通过多版本读一致性模型(Multiversion Read Consistency)来提供数据的一致性和并发性上篇回顾:事务具有一致性属性,即事务须将数据库从一个一致性状态带到另一个一致性状态Oracle 通过保留修改过的数据块在修改之前和之后的状态,以能够基于事务请求信息的某个特定时间点以及事务隔离级别来同时显示数据的多个版本,从而数据库可以在某一个时间点上的多个会话重建数据的一致性视图撤销数据块中保留数据之前的状态,而重做信息保存在 SGA(系统共享区)的在线重做日志中,重做日志中包含数据块的修改以及对撤销块的修改在事务提交修改以后,SGA 数据库缓冲区会进行更新,但修改不一定会马上写入到数据文件中Oracle 使用系统变更号(SCN)记录实例中所发生的变更的顺序并将变更与某个时间点联系起来,如果数据库闪回到了 SCN 标明的时间点上,任何在这一时间点之后提交的事务都将不再在数据库中存在,这可以有效地阻止“部分事务”被存储到数据库中闪回:Oracle 能保证数据一致性的唯一方法就是对所有没有提交的工作进行回滚
总共只有五个事务控制语句(TCL):COMMIT、SAVEPOINT、ROLLBACK、SET TRANSACTION 以及 SET CONSTRAINTSCommit 通过使你的修改持久化并对其他用户可见来结束事务,默认的行为以 commit write wait immediate 来处理提交而异步提交(nowait)允许数据库在修改被持久化之前确认已经收到了你的修改,如果数据库在提交被写入之前失败了,你的事务就将不复存在这里涉及到一些有关 Oracle 数据库原理的知识,简单来说当提交指令发出时,数据库并非直接将修改写入磁盘,在此之前还有一些工作完成,比如要将为修改保留的重做(Redo)信息从日志缓存写入日志文件,同步提交则要求等待所有工作都完成后才将控制权返回给提出 Commit 的进程,所谓异步提交就是不等待数据库完成所有工作,立即返回控制权,从而不能保证修改一定生效,适用于在一定场景中提高执行速度
Savepoint 使得你可以在事务中标记特定的点并将你的事务回滚到某个特定的 savepoint,注意保存点是顺序的
<some transactions here>
SAVEPOINT SPA;
<some transactions here>
SAVEPOINT SPB;
<some transactions here>
--注意保存点是顺序的,回滚到保存点A,则保存点B前的事务也不被保留
--只有回滚到某保存点,没有保存到某保存点
ROLLBACK TO SAVEPOINT SPA;
Rollback 是结束事务的另一个选项,如果你选择回滚修改就都会被退回,所有数据返回到之前的一致性状态
亦可以选择返回到某个特定的保存点,但回滚到保存点并不会结束事务,事务会保持活动状态直到彻底回滚或提交Set transaction read only 将会提供可重复读隔离级别但你将不能修改数据Set transaction isolation level serializable 命令指定序列化隔离级别,这时你可以修改数据使用 Set Constraint[s] 可以将约束检验推迟,因为默认在执行 DML 语句之后就要立即检验表的约束条件,而使用 Set Constraint[s] 可以在当前事务中推迟一切可以推迟的约束推迟,也就是推迟到事务提交的时候才进行约束检验这个指令既可以推迟某个单独的约束,也可以推迟所有的约束

当你发起第一条 SQL 语句修改数据(增、删、改都属于数据修改)时,数据库就识别出了一个活动的事务并为之创建一个事务 ID,在事务中事务 ID 将保持不变,且此 ID 只会在事务活动期间你的修改还是待定的时候存在前文说的 SCN 编号标识数据库中的一个特定时间点,它可以用来将数据库还原到之前的一个时间点的同时保证数据的一致性,SCN 编号会不断增加而不管你在事务处理中处于什么步骤--查询数据库当前的SCN
SELECT current_scn FROM v$database;
--事务的数据字典
SELECT xid, status FROM v$transaction;
--将事务和会话关联
SELECT t.*
FROM v$transaction t, v$seesion s
WHERE t.addr = s.taddr
AND s.sid = userenv('SID');

当事务在序列化模式下执行时,Oracle 的多版本读一致性模型就会在事务开始时创建数据视图不管有多少事务会同时对数据进行更新,序列化事务将只会看到自己的修改在序列化模式下执行事务并不意味着更新是串行处理的,如果序列化事务尝试更新一条在事务开始后已经发生了变化的记录(例如被其它事务更新并提交过),更新将不被允许(在提交时报错)要想使序列化事务成功完成,就需要在事务执行过程中不会有其它人来更新同样的数据,故要保证序列化事务尽可能短和快地完成自治事务可以提交或回滚自己的修改而不影响调用它的外部主事务CREATE OR REPLACE PROCEDURE|FUNCTION <clause> IS
PRAGMA AUTONOMOUS_TRANSACTION;
<more codes here>
注意自治事务中必须结束自己的事务,否则会报错(运行时错误)
