关于事务

1、什么是事务

数据库事务(Database Transaction)是一组数据库操作的处理单元。事务符合ACID的特征:
  Atomic:原子性,要么全部要么一无所有。All or None.
  Consistent:一致性,所有依赖联系以及约束一致。
  Isolated:分离性,不同事务不互相影响。
  Durable:持久性,提交事务的数据须要持久化。
2、为什么要运用事务

实现事务主要有两大功能:
  A、保证数据库的consistent(一致性状态),保持所有依赖联系以及约束一致)。哪怕数据库管理系统出现故障时(例如断电),也可以恢复到一致性状态。例如一个银行转帐系统,张三给李四转3000圆RMB,张三帐号上减3000和李四帐号上加3000须要同时完成,否则系统的帐就不平了。也例如有些销售系统的汇总表和明细表,是一个主表和一个从表,须要同步更新。
  B、并发时分离不同事务操作。例如编辑流程中的数据不给其他事务查询到。这也是相对的,在特殊效果需求下可能要支持dirty read(脏读),但不是这里讨论的范围了。

3、Oracle的事务类型

Oracle的事务处理类型有点像SQL Server的隐式事务。当执行到第一个可执行的SQL语句时自动打开事务,然后须要调用方执行commit或者rollback来提交或者回滚事务,如果有DDL语句,Oracle也会自动提交事务的。
  参考:Transaction Management

4、Oracle的事务的实现

Oracle的结构分逻辑上和物理上的区别。逻辑上的结构是表空间,而物理上的结构是数据文件。
  逻辑实现
  Oracle下实现事务在逻辑上是由Undo Tablespace来实现的。Undo Tablespace包含Undo Segements(段),而Undo Segements包含Undo Data。Undo Data是支持事务的逻辑单元。
Undo Data用于保存修改前后的数据,以支持回滚,长时间查询,和flashback查询,以及失败事务恢复的功能。
  由于有了Undo Data,回滚事务变得容易了,因为Undo Data保存了修改前后的数据,保证了事务的原子性。失败事务恢复和事务回滚类似,当网络中断或者其他原由导致事务异常停止,数据库引擎可以恢复到一致性状态。
  同时Undo Data也支持长时间查询(Read-consistent),例如有表格T,主键为key,有字段为f1,数据如下,key
  f1
1A2B3C4D
  事务一开始查询,一直没结束,而事务二开始修改key为1的数据为Z,事务二执行 提交,数据变成下面的表格。但是事务一查询结束的时候还是读出A,B,C,D,因为查询是从Undo中读出快照。
  key
  f1
1Z2B3C4D
  Flashback查询是Oracle 10g引进的功能,可以查询出提交之后修改之前的数据,例如上面例子事务三在事务二提交后想查询出A,B,C,D可以通过Flashback查询来完成。这也是有Undo Data来支持的。
物理实现
  从上面的逻辑实现看,只是知道了事务以及Undo Data的作用,还不清楚Oracle对事务的支持到底如何实现的。下面从物理结构上讲述Oracle如何对事务执行 支持。请先看一个物理结构图。
尽管只有4条数据,假设须要很长时间执行 查询。
为了简化,我只是用个人的语言讲述和事务有关的部件。SGA可以理解为全局内存。其中Database Buffer Cache存放的是从数据文件中读取的数据缓存。紫色的圆柱体为数据文件。Redo Log Buffer为重做日志缓存,也就是保存日志的内存块,一切的数据的修改都会记录在Redo Log Buffer里面。例如用回事务二更新key为1数据的例子。当事务二更新key为1数据从A到Z。Oracle数据库引擎会把key为1的数据的 rowid,修改前数据A以及修改后数据Z都记录在Redo Log Buffer里面。如果事务二继续更新key为2的数据为Y,那么key为2的数据的rowid,修改前数据B以及修改后数据Y也记录到Redo Log Buffer里面。每一笔数据都记录,而且是流水线性记录。一旦事务二执行 提交,LGWR进程(Log Writer,日志写进程)就会把Redo Log Buffer的数据按顺序写到Log Datafile里面,也就是日志数据文件里面,当写日志文件完成,Oracle数据库引擎会生成一个SCN(system change number,系统更新号),到这时候Oracle数据库引擎会通知调用方提交完成了。这里可以看到Oracle在提交的时候不必要把更新数据写回数据文件,而是写到日志文件里面。因为顺序写线性的日志文件速度快很多,而写数据文件是须要随机读写。由于线性记录和SCN号控制,数据库引擎可以通过redo log(重做日志文件)的操作得到最新的数据。当然在Checkpoint的时候数据文件是最终还是会更新的,只是说事务提交的时候更新数据文件不是必须步骤,这样能很大的提高性能。
  由于这个机制,回滚变得很基本,要读没提交前之前的SCN是很容易的事情。
  对于初学者关于数据库事务处理的建议
  我自己也是从新手一步步走过来,现在也不是老鸟,算是有点体会,如果是刚入门的同学,你觉得有用就看一下,没用就过了。
  对于数据库事务的处理,开始的时候不须要很深入了解数据库的原理,当然以后还是须要了解的,优先级排后而已。高优先级如下:
  首先,事务不是什么高深神秘的东西,我从入行开始所做的所有系统,包括现在的嵌入式系统,都用到事务。我并不觉得大部分系统事务有什么疑问,只是一些约束和同步机制,真的有疑问从自身系统设计角度看,不一定说从数据库技能角度去找处理要领。例如Oracle的长时间查询如果Undo Data(历史数据)给覆盖了,Oracle会抛出异常"ORA-01555: snapshot too old”,如果出现这种疑问,我会从自身系统设计角度入手,为什么有那么大的查询,为什么在这个查询中其他事务会更新数据,这些查询能不能只是查一次就够了,查的流程能不能须要锁住表等等。然而这个疑问可以通过数据库调优处理,但是我想疑问的角度首先是从自身系统设计出发。
  第二,要知道的是不同数据库的事务类型的区别,例如MS SQL Sever是默认是自动提交事务,用的时候须要知道每个语句都有单独的事务在操作。而Oracle是类似于隐式事务,必须手工commit或者rollback。
  第三,运用事务要知道一一对应,特别是嵌套事务的时候,有始有终。很多疑问时候发生终的时候,留心异常处理须要结束已经打开的事务。
  第一点是心理疑问,第二三点是技能疑问,做好我觉得就可以入门开发系统了。以后碰到疑问在一步步深入。
  MS SQL Server对事务的实现下一篇再讲了。上述是我对Oracle实现的理解,有不当之处也希望指出,我可以完备文章。
 

你可能感兴趣的:(职场,事务,休闲)