`
linsea
  • 浏览: 90071 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

事 务

阅读更多

 

 

Oracle中的事务体现了所有必要的ACID特征。ACID是以下4个词的缩写:

l         原子性(atomicity) :事务中的所有动作要么都发生,要么都不发生。

l         一致性(consistency) :事务将数据库从一种一致状态转变为下一种一致状态。

l         隔离性(isolation) :一个事务的影响在该事务提交前对其他事务都不可见。

l         持久性(durability) :事务一旦提交,其结果就是永久性的。

 

8.1   事务控制语句

Oracle 中不需要专门的语句来“开始事务”。隐含地,事务会在修改数据的第一条语句处开始(也就是得到 TX 锁的第一条语句)。

可以使用哪些事务控制语句:

COMMIT:要想使用这个语句的最简形式,只需发出COMMIT

ROLLBACK:要想使用这个语句的最简形式,只需发出ROLLBACK

SAVEPOINTSAVEPOINT允许你在事务中创建一个“标记点”(marked point) ,一个事务中可以有多个SAVEPOINT

ROLLBACK TO <SAVEPOINT>:这个语句与SAVEPOINT命令一起使用。可以把事务回滚到标记点,而不回滚在此标记点之前的任何工作。

SET TRANSACTION:这条语句允许你设置不同的事务属性,如事务的隔离级别以及事务是只读的还是可读写的。使用手动undo管理时,还可以使用这个 来指示事务使用某个特定的 undo 段,不过不推荐这种做法。

 

8.2   原子性

8.2.1 语句级原子性

Oracle 保证最初的 INSERT(即导致触发器触发的插入语句)是原子性的,这个INSERT INTOT是语句,所以INSERT INTO T的任何副作用都被认为是语句的一部分。为了得到这种语句级原子性,Oracle悄悄地在每个数据库调用外面包了一个SAVEPOINT。前面的两个INSERT实际上处理如下:

Savepoint statement1;

Insert into t values ( 1 );

If error then rollback to statement1;

Savepoint statement2;

Insert into t values ( -1 );

If error then rollback to statement2;

Oracle中,这种语句级原子性可以根据需要延伸。在前面的例子中,如果INSERT INTO T触发了一个触发器,这个触发器会更新另一个表,而那个表也有一个触发器,它会删除第三个表(以此类推),那么要么所有工作都成功,要么无一成功。为保证这一点,无需你编写任何特殊的代码,Oracle本来就会这么做。

8.2.2 过程级原子性

OraclePL/SQL匿名块也当作是语句。

ops$tkyte@ORA10G> create or replace procedure p

2 as

3 begin

4 insert into t values ( 1 );

5 insert into t values (-1 );

6 end;

Oracle 把这个存储过程调用处理为一个原子语句。客户提交了一个代码块 BEGIN  P;  END;Oracle 在它外面包了一个SAVEPOINT。由于 P 失败了,Oracle 将数据库恢复到调用这个存储过程之前的时间点。下面,如果提交一个稍微不同的代码块,会得到完全不同的结果:

ops$tkyte@ORA10G> begin

2 p;

3 exception

4 when others then null;

5 end;

6 /

在此,我们运行的代码块会忽略所有错误,这两个代码块的输出结果有显著的差别。尽管前面第一个 P 调用没有带来任何改变,但在这里的P调用中,第一个INSERT会成功,而且T2中的CNT列会相应地递增。

Oracle把客户提交的代码块认为是“语句”。这个语句之所以会成功,因为它自行捕获并忽略了错误,所以If error then rollback…没有起作用,而且执行这个语句后Oracle没有回滚到SAVEPOINT。因此,这就保留了P完成的部分工作。为什么会保留这一部分工作呢?首要的原因是 P 中有语句级原子性:P 中的每条语句都具有原子性。P提交其两条 INSERT 语句时就成为 Oracle 的客户。每个INSERT 要么完全成功,要么完全失败。从以下事实就可以证明这一点:可以看到,T上的触发器触发了两次,而且将T2更新了两次,不过T2中的计数只反映了一个UPDATEP中执行的第二个INSERT外包着一个隐式的SAVEPOINT

 

8.2.3 事务级原子性

事务也是原子性的,事务完成的所有工作要么完全提交并成为永久性的,要么会回滚并撤销。

 

8.3   完整性约束和事务

需要指出到底什么时候检查完整性约束。默认情况下,完整性约束会在整个SQL语句得到处理之后才进行检查。也有一些可延迟的约束允许将完整性约束的验证延迟到应用请求时(发出一个 SET  CONSTRAINTS  ALL  IMMEDIATE 命令)才完成,或者延迟到发出

COMMIT时再检查。

8.3.1 MMEDIATE 约束

这是一般情况。在这种情况下,完整性约束会在整个SQL语句得到处理之后立即检查。注意,这里我用的是“SQL 语句”而不只是“语句”。如果一个 PL/SQL 存储过程中有多条 SQL 语句,那么在每条 SQL 语句执行之后都会立即验证其完整性约束,而不是在这个存储过程完成后才检查它。 那么,为什么约束要在 SQL 语句执行之后才验证呢?为什么不是在 SQL 语句执行期间验证?这是因为,一条语句可能会使表中的各行暂时地“不一致”(如SQL语句:update t set x=x+1),这是很自然的。尽管一条语句全部完成后的最终结果是对的,但如果查看这条语句所做的部分工作,会导致 Oracle拒绝这个结果。

 

8.3.2 DEFERRABLE 约束和级联更新

Oracle8.0开始,我们还能够延迟约束检查,对于许多操作来说,这很有好处。首先能想到的是,可能需要将一个主键的UPDATE级联到子键。也许很多人会说:这没有必要,因为主键是不可变的(我就是这些人之一),但是还有人坚持要有级联 UPDATE。有了可延迟的约束,就使得级联更新成为可能。

注意创建子表的语法如下(父表的创建略):

ops$tkyte@ORA10G> create table c

2 ( fk constraint c_fk

3 references p(pk)

4 deferrable

5 initially immediate

6 )

7 /

Table created.

这个约束创建为一个DEFERRABLE约束,但是设置为 INITIALLY  IMMEDIATE。这说明,可以把这个约束延迟到 COMMIT 或另外某个时间才检查。不过,默认情况下,这个约束在语句级验证。这是可延迟约束最常见的用法。大多数现有的应用不会在 COMMIT 语句上检查约束冲突,你最好也不要这么做。

迟延更新的方法如下:

ops$tkyte@ORA10G> set constraint c_fk deferred;

Constraint set.

ops$tkyte@ORA10G> update p set pk = 2;

1 row updated.

Commit complete. ops$tkyte@ORA10G> update c set fk = 2;

1 row updated.

ops$tkyte@ORA10G> set constraint c_fk immediate;

Constraint set.

ops$tkyte@ORA10G> commit;

这就是级联更新的做法。注意,要延迟一个约束,必须这样来创建它们:先将其删除,再重新创建约束,这样才能把不可延迟的约束改变为可延迟约束。

 

8.4   不好的事务习惯

一般的数据库认为锁是稀有资源,另外读取器会阻塞写入器,反之,写入器也会阻塞读取器。为了提高并发性,这些数据库希望你的事务越小越好,有时甚至会以数据完整性为代价来做到这一点。Oracle 则采用了完全不同的方法。事务总是隐式的,没有办法“自动提交”事务,除非应用专门实现。在Oracle中,每个事务都应该只在必要时才提交,而在此之前不能提交。事务的大小要根据需要而定。锁、阻塞等问题并不是决定事务大小的关键,数据完整性才是确定事务大小的根本。锁不是稀有资源,并发的数据读取器和数据写入器之间不存在竞争问题。这样在数据库中就能有健壮的事务。这些事务不必很短,而要根据需求有足够长的持续时间(但是不能不必要地太长)。事务不是为了方便计算机及其软件,而是为了保护你的数据。

一般不好的思维习惯:

l         频繁地提交大量小事务比处理和提交一个大事务更快,也更高效。

l         没有足够的undo空间。

但其实最好的方法是按业务过程的要求以适当的频度提交,并且相应地设置undo段大小。

 

8.4.1 在循环中提交

1. 性能影响

    如果进行大批量的更新删除操作,最好用一条SQL语句完成,而不要受惯性思维的影响进行批量的提交(如每100条提交一次),这样性能反而不好。

    下面再对这个讨论做个补充,给出一个对应的例子。应该记得在第7章中,我们讨论过写一致性的概念,并介绍了UPDATE语句如何导致重启动。 如果要针对一个行子集 (有一个WHERE  子句)执行先前的UPDATE语句,而其他用户正在修改这个UPDATEWHERE子句中使用的列,就可能需要使用一系列较小的事务而不是一个大事务,或者更适合在执行大量更新之前先锁定表。这样做的目标是减少出现重启动的机会。如果要UPDATE表中的大量行,这会导致我们使用LOCK TABLE命令。不过,根据我的经验,这种大量更新或大量删除(只有这些语句才可能遭遇重启动)都是独立完成的。一次性的大量更新或清除旧数据通常不会在活动高发期间完成。实际上,数据的清除根本不应受此影响,因为我们一般会使用某个日期字段来定位要清除的信息,而其他应用不会修改这个日期数据。

 

2. Snapshot Too Old错误

如果像前面的那个例子一样,你一边在读取表,一边在修改这个表,就会同时生成查询所需的 undo 信息。UPDATE 生成了undo信息,你的查询可能会利用这些undo信息来得到待更新数据的读一致视图。如果提交了所做的更新,就会允许系统重用刚刚填写的undo段空间。如果系统确实重用了undo段空间,擦除了旧的undo数据(查询随后要用到这些undo信息) ,你就有大麻烦了。SELECT会失败,UPDATE也会中途停止。(为什么?)这样就有了一个部分完成的逻辑事务,而且可能没有什么好办法来重启动

ORA-01555错误的例子会使更新处于一种完全未知的状态。有些工作已经做了,而有些还没有做。如果在游标的FOR循环中提交,要想避免ORA-01555,我绝对是无计可施。 ORA-30036 错误是可以避免的,只需在系统中分配适当的资源。通过设置正确的大小就可以避免这个错误;但是第一个错误(ORA-01555)则不然。另外,即使我未能避免 ORA-30036 错误,至少更新会回滚,数据库还是处于一种已知的一致状态,而不会半路停在某个大更新的中间。另外可以通过视图V$UNDOSTAT观察所生成的UNDO数量。

 

3. 可重启动的过程需要复杂的逻辑

如果采用“在逻辑事务结束之前提交”的方法,最验证的问题是:如果 UPDATE 半截失败了,这会经常将你的数据库置于一种未知的状态中。除非你提取对此做了规划,否则很难重启动这个失败的过程,让它从摔倒的地方再爬起来。所以要考虑编写可重启动的逻辑程序,但这可能会很复杂。

推荐的做法:力求简单。如果能在SQL中完成,那就在SQL里完成。如果不能在SQL中完成,就用PL/SQL实现。要用尽可能少的代码来完成,另外应当分配充分的资源。一定要考虑到万一出现错误会怎么样。应当正确地设置 undo 段的大小,比起编写一个可重启动的程序来说,前者要容易得多。

 

8.1 分布式事务

Oracle 有很多很好的特性,其中之一就是能够透明地处理分布式事务。Oracle中分布式事务的关键是数据库链接 (database link)。它使用了一个 2PC 协议来做到这一点。2PC 是一个分布式协议,如果一个修改影响到多个不同的数据库,2PC允许原子性地提交这个修改。在多个数据库之间的一个2PC事务中,其中一个数据库(通常是客户最初登录的那个数据库)会成为分布式事务的协调器。这个站点会询问其他站点是否已经准备好提交。实际上,这个站点会转向其他站点,问它们是否准备就绪。其他的每个站点会报告它的“就绪状态“(YESNO) 。如果只要有一个站点投票 NO,整个事务就会回滚。如果所有站点都投票 YES,站点协调器会广播一条消息,使每个站点上的提交成为永久性的。

    对于分布式事务,还存在一些限制(不过并不多),其中重要的限制如下:

l         不能在数据库链接上发出COMMIT。也就是说,不能发出COMMIT@remote_site。只能从发起事务的那个站点提交。

l         不能在数据库链接上完成 DDL。这是上一个问题带来的直接结果。DDL会提交,而除了发起事务的站点外,你不能从任何其他站点提交,所以不能在数据库链接上完成DDL

l         不能在数据库链接上发出SAVEPOINT。简单地说,不能在数据库链接发出任务事务控制语句。所有事务控制都有最初打开数据库链接的会话继承得来;对于事务中的分布式实例,不能有不同的事务控制。

 

8.5   自治事务

自治事务(autonomous transaction)允许你创建一个“事务中的事务” ,它能独立于其父事务提交或回滚。 自治事务提供了一种用PL/SQL控制事务的新方法,可以用于:

l         顶层匿名块;

l         本地(过程中的过程) 、独立或打包的函数和过程;

l         对象类型的方法;

l         数据库触发器。

例如:

ops$tkyte@ORA10G> create or replace procedure Autonomous_Insert

2 as

3 pragma autonomous_transaction;

4 begin

5 insert into t values ( 'Autonomous Insert' );

6 commit;

7 end;

8 /

Procedure created.

 

注意这里使用了pragma AUTONOMOUS_TRANSACTION。这个指令告诉数据库:执行这个过程时要作为一个新的自治事务来执行,而且独立于其父事务。

注意:pragma是一个编译器指令,这是一种编辑器执行某种编译选项的方法。还有其他一些pragma。参考PL/SQL编程手册,可以看到其索引中有pragma的一个列表。

 

总结一下,如果在一个“正常”的过程中 COMMIT,它不仅会持久保留自己的工作,也会使该会话中未完成的工作成为永久性的。不过,如果在一个自治事务过程中完成COMMIT,只会让这个过程本身的工作成为永久性的。

 

 

 

 

分享到:
评论

相关推荐

    第9章 事 务 与 锁

    事务是并发控制的基本单位。所谓事务,就是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。

    律师事务所对申请人的实习鉴定意见_2020年律师事务所毕业实习评语(精品)..doc

    该篇对实习生的工作表现和个人素质进行了评价,认为其能够坚持正确的政绩观,说实话、务实事、求实效等。同时,也指出了实习生的缺点,希望其不盲目攀比、不搞花架子等。 第四篇:律师事务所对申请人的实习鉴定意见...

    MySQL面试题含答案

    1.MySQL 数据库作发布系统的存储,一天五万条以上的增量, 预计运维三年,怎么优化? 2.SQL注入漏洞产生的原因?... MYSQL 表类型是使用 InnoDB Tables 或 BDB tables 的话,你的 MYSQL 就 可 以 使 用 事 务 处 理。

    分布式事务.pdf

    这篇文章将介绍什么是分布式事务,分布式...相信耐心看完这篇文章,谈到分布式事务,不再只是有“2PC”、“3PC”、“MQ的消息事 务”、“最终一致性”、“TCC”等这些知识碎片,而是能够将知识连成一片,形成知识体系。

    SQL Server 2005课件ppt

    第9章 事 务 与 锁 第10章 索 引 第11章 规 则 第12章 默认值 第13章 存 储 过 程 第14章 触 发器 第15章 SQL Server 2005的安全性 第16章 备份与恢复 第17章 XML 第18章 SQL Server分析服务 第19章 SQL Server报表...

    人力资源管理系统(HRM)源码[实习项目]

    人力资源管理系统(HRM)源码 HR 演示系统以企业内部人力资源...无论是后台的事 务、存储、分布式计算等基础服务,还是前端的UI展现与用户交互,以及后台与前端的会话过程,Apusic OperaMasks都提供了完整的解决方案.

    星环-transwarp-inceptor-V5.1使用手册

    Transwarp Inceptor可提供完整的SQL支持,支持主流的SQL模块化扩展,兼容通用开发框架和工具,支持事 务特性保证数据的准确性,允许多租户的隔离与管理,且能够利用内存或者SSD来加速数据的读取,支持与关 系型...

    四川师范大学SQLserver数据库课件

    第9章 事 务 与 锁 第10章 索 引 第11章 规 则 第12章 默认值 第13章 存 储 过 程 第14章 触 发器 第15章 SQL Server 2005的安全性 第16章 备份与恢复 第17章 XML 第18章 SQL Server分析服务 第19章 SQL Server报表...

    会计师事务所注册会计师审计师行业专长2014-2022客户审计费用数量营业收入总资产维度

    会计师事 务所名称 股票代码 会计年度 注册会计 师姓名 共同签字注册会计师 签字排名 事务所行业专长5 事务所行业专长5SQRT 事务所行 业专长6 事务所行业专长6SQRT 注册会计师行业专 长5 注册会计师行业专长5SQRT ...

    SQL Server 2005数据库课件PPT

    第1章 数据库基础 第2章 SQL Server 2005的安装与配置 第3章 SQL Server 2005的常用工具 第4章 管理数据库 第5章 表 第6章 数据操作实例 第7章 视 图 第8章 T-SQL语言 第9章 事 务 与 锁...

    银行审计信息数据1954-2022年

    AudAF[审计会计师事 务所]-审计会计师所在的事务所 AudDate[审计日期]-注册会计师出具审计报 告的日期 Auditor1[审计师姓名1]-对公司进行审计的签字注册会计师姓名, 如有两位审计师,则分别填入审计师姓名1与审计师...

    Java技术中数据的持久化实现及对比.pdf

    它 是 可 选 的,只 有 在 编 写 自己 的 底 层 事 务 处 理 代 码 时 才 需 要 ;Query 接 口 负 责 执 行 各 种 数 据 库 查询 ;Configuration 接 口 负 责 配 置 并 启 动 Hibernate,创 建 SessionFactory 对 ...

    推荐上市公司客户与审计师不匹配关系计算Stata代码(附2007-2022年数据)

    户选择Big4事务所的估计概率在最佳临界值以上,则该客户被认为是潜在的Big4事 务所客户;如果客户选择Big4事务所的估计概率等于或在最佳临界值以下,则该客户被 认为是潜在的Non-Big4事务所客户。每个客户的期望选择...

    推荐上市公司客户与审计师不匹配关系计算Stata代码(附2007-2021年数据)

    户选择Big4事务所的估计概率在最佳临界值以上,则该客户被认为是潜在的Big4事 务所客户;如果客户选择Big4事务所的估计概率等于或在最佳临界值以下,则该客户被 认为是潜在的Non-Big4事务所客户。每个客户的期望选择...

    信息化运维费用分解方法 XXXX0824.pdf

    综 合事 务类运维人工费用是指为保 障运维工作的规 范化、有序开展,所需的一系列综合性的运维管理费用,如资产管理、流程管理、用户培训、知识管理、服务台等。 信息化运维费用计算方法是根据单项任务的工作量和...

    基于Struts和Hibernate技术的企业管理信息系统研究与开发

    对象的思想来操作关系型数据库的各类数据,同时 Hibernate 还提供了灵活的事 务处理和查询机制。通过以上两个框架的整合应用,可以形成一个灵活、松耦 合和易于扩展维护的信息系统的完整解决方案。 本论文以江苏省...

Global site tag (gtag.js) - Google Analytics