




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
前言首先思考一个问题:如果对数据库进行了多次修改,如果前面的修改成功,后面修改时发生了意外,怎么办?案例:以银行转账为例。有帐户表记录如下:帐号 姓名 余额1 张三 20002 李四 1000假设张三给李四转账300块,则对数据库的修改必然有两步:第一步:减少张三的余额:20001700第二步:增加李四的余额:10001300但是如果第一步完成以后,马上就死机(或者断电、地震)了。等数据库重启以后,目前的帐户情况变为:帐号 姓名 余额1 张三 17002 李四 1000这表示,张三的余额减少了,但是李四并没有收到转账的钱。说明:在实际的银行项目中,转账不会是只有一个帐户表,直接进行余额修改。在此简化的目的是为了便于说明事务的相关概念。思考:数据库如何操作才能避免这种情况发生呢?要解决上面的问题,必须学习一个新的知识点:事务,这是数据库中非常重要的概念,必须掌握!问题:为什么要事务?回答:在对数据进行多次增删改以后,如果要保证所有的操作同时成功,或者同时失败。必须使用事务。问题:什么是事务?回答:事务就是业务上的一个逻辑工作单元,它能够保证其中对数据所有的操作,要么全部成功,要么失败。例如在转账时,一个帐户要增加余额,一个帐户要减少余额,这两个操作在业务上必须当一个整体,也叫做“一个逻辑工作单元”。“符合逻辑”就是指满足符合业务要求。问题:事务的原理是什么?回答:主要依赖于日志。如果事务没有完成,则日志中没有结束标记,数据库就会执行前面各步的反向操作,例如:1、事务开始张三减300(20001700)死机。2、数据库重启读取日志,检查事务没有结束标记,执行“反向”操作张三加300(17002000)张三数据恢复了。说明:数据库事务恢复的过程其实是很很复杂的,在此只是讲解最基本的原理。问题:事务有哪些特征?回答:一共有4个:原子性:以转账为例。帐户减少和帐户增加是两个DML语句,但是被当一个“原子”,所以外部程序是不知道这个原子中有几个SQL的。更不能只执行其中一个SQL,只能同时成功,或者同时失败。即:无法拆出事务中某一条SQL语句来单独执行。一致性:要么都是改变前的改变,要么都是改变后的状态。例如:转账前分别是1000和2000,总和3000;转账300后分别是1300和1700,总和也是3000。这就叫做一致性。不一致就是,转账后分别1300和2000(不变),总是3300,一个是改变后的状态,另一个还是改变前的状态。隔离性:在某个时间段,肯定有很多人都在转账,每个人的转账都是在一个自己的事务中,所以在一个数据库中,有很多事务会同时存在。虽然同时存在很多事务,但是事务之间不会相互影响。持久性:如果事务提交成功,则数据修改永远生效;如果是回滚,则数据完全没有被修改,就相当于没有这件事情发生。事务结束以后,必须重新启动一个新的事务才能修改数据。说明:可以用口诀(一原永隔)来帮助记忆。问题:如何使用事务?回答:一共有三步。1、先开启事务。在Oracle中,事务是在上一次事务结束以后,数据“第一次”被修改时自动开启。在java中,设置连接为手动提交模式开始。代码:connection.setAutoCommit(false)。2、进行(多次)数据操作(增删改)3、结束事务: commit、rollback。问题:如何结束事务?回答:有两种方法:1、确认对数据的修改:提交,commit。2、撤消对数据的修改:回滚,rollback。另外,当Oracle系统或者PL/SQL脚本抛出异常,都会造成数据回滚。问题:能不能做局部提交或者局部回滚?如执行了三个insert语句,能不能只提交或者回滚前面2个。回答:如果说要提交,只能提交所有的sql语句。如果说要回滚,可以利用“事务保存点”来做局部回滚。注意,此时事务并没有结束。示例:执行:1、 insert into dept values(50,a,null);2、 insert into dept values(60,b,null);3、 savepoint a;4、 insert into dept values(70,c,null);5、 rollback to savepoint a;问题:现在插入了几个新部门?分析:回滚到保存点“a”,表示保存点以后的所有数据操作取消。所以只插入了两个部门。问题:现在的事务结束了吗?回答:没有,必须再执行commit或者rollback来结束事务。说明:在工作中这种“局部回滚”用得比较少。示例:异常与事务。问题:假设现在有50和60两个新部门。执行下面代码以后,这两个部门删除了没有?begindelete from dept where deptno=50;delete from dept where deptno=60;raise_application_error(-20000,抛个异常玩);end;分析:没有。因为抛出异常以后,数据库会自动回滚。问题:现在再执行commit,是否删除了?回答:还是没有。因为事务在回滚以后,事务结束,这表示刚才执行的sql语句完全不存在了,所以如果还要删除,则必须重新执行sql语句。即:在事务结束以后,再执行commit和rollback是没有用的。问题:什么是提交模式,与事务有什么关系?回答:提交模式有两种:自动提交:在每一次数据被修改以后,自动提交。这种模式下是无法支持事务的。手动提交:所有的数据修改都在内存中,当执行commit时才一起提交。只要有一条sql执行失败,则所有的sql自动回滚。只能在手动提交模式下才能使用事务。问题:事务有哪几种隔离级别?回答:事务隔离级别在理论上有4种,从低到高分别是:未提交读:一个事务可以读到其它事务未提交的数据。提交读:一个事务只能读到其它事务已提交的数据。可重复读:一个事务中,不管数据有没有被其它事务所修改,读到的数据都是不变的。串行读:一个事务要操作数据,必须要等到其它事务结束才能访问,包括查询。Oracle只支持其中两种: 提交读和串行读,默认就是提交读。问题:数据库为什么要在理论上分这4种隔离级别,通常用哪一种呢?回答:事务隔离级别越高,则并发性越低,即能够同时使用数据库的人就越少。虽然未提交读性能最高,但是会造成数据不一致(这叫:脏读)。而串行读能最大限度的保护数据,但性能又太低。所以通常要在性能和安全之间做一个选择,在Oracle中,就使用默认的隔离级别:提交读什么是事务数据库事务(Database Transaction)是一组数据库操作的处理单元。事务符合ACID的特性:Atomic:原子性,要么全部要么一无所有。All or None.Consistent:一致性,所有依赖关系以及约束一致。Isolated:分离性,不同事务不互相影响。Durable:持久性,提交事务的数据需要持久化。为什么要使用事务实现事务主要有两大功能:1.保证数据库的consistent(一致性状态),保持所有依赖关系以及约束一致)。哪怕数据库管理系统出现故障时(例如断电),也能恢复到一致性状态。例如一个银行转帐系统,张三给李四转3000圆RMB,张三帐号上减3000和李四帐号上加3000需要同时完成,否则系统的帐就不平了。也例如有些销售系统的汇总表和明细表,是一个主表和一个从表,需要同步更新。2.并发时分离不同事务操作。例如编辑过程中的数据不给其他事务查询到。这也是相对的,在特效需求下可能要支持dirty read(脏读),但不是这里讨论的范围了。SQL Server 2008 的事务类型1.自动提交事务 Autocommit Transactions这是SQL Server默认的事务类型,每一条单独的SQL语句(SQL statement)都是单独的一个事务,语句执行完毕后自动提交。调用方不需要手工控制事务流程。2.显示事务 Explicit Transactions调用方需要调用API或者使用T-SQL的BEGIN TRANSACTION 语句来打开事务。需要调用COMMIT 或者 ROLLBACK TRANSACTION 来提交或者回滚。3.隐式事务 Implicit Transactions使用SET IMPLICIT_TRANSACTIONS ON把事务模式变成隐式模式。调用方不需要执行BEGIN TRANSACTION 语句来打开事务。数据库引擎执行到SQL语句的时候自动打开事务。调用方需要调用COMMIT 或者 ROLLBACK TRANSACTION 来提交或者回滚。当数据库引擎执行下一个SQL语句时又自动打开一个新事务。参考:Controlling Transactions (Database Engine)Oracle的事务类型Oracle的事务处理类型有点像SQL Server的隐式事务。当执行到第一个可执行的SQL语句时自动打开事务,然后需要调用方执行commit或者rollback来提交或者回滚事务,如果有DDL语句,Oracle也会自动提交事务的Oracle的事务的实现Oracle的结构分逻辑上和物理上的区别。逻辑上的结构是表空间,而物理上的结构是数据文件。逻辑实现Oracle下实现事务在逻辑上是由Undo Tablespace来实现的。Undo Tablespace包含Undo Segements(段),而Undo Segements包含Undo Data。Undo Data是支持事务的逻辑单元。图源自于Oracle Database 10g: Administration Workshop IUndo Data用于保存修改前后的数据,以支持回滚,长时间查询,和flashback查询,以及失败事务恢复的功能。由于有了Undo Data,回滚事务变得容易了,因为Undo Data保存了修改前后的数据,保证了事务的原子性。失败事务恢复和事务回滚类似,当网络中断或者其他原因导致事务异常停止,数据库引擎可以恢复到一致性状态。同时Undo Data也支持长时间查询(Read-consistent),例如有表格T,主键为key,有字段为f1,数据如下,尽管只有4条数据,假设需要很长时间进行查询。事务一开始查询,一直没结束,而事务二开始修改key为1的数据为Z,事务二进行提交,数据变成下面的表格。但是事务一查询结束的时候还是读出A,B,C,D,因为查询是从Undo中读出快照。Flashback查询是Oracle 10g引进的功能,可以查询出提交之后修改之前的数据,例如上面例子事务三在事务二提交后想查询出A,B,C,D可以通过Flashback查询来完成。这也是有Undo Data来支持的物理实现从上面的逻辑实现看,只是知道了事务以及Undo Data的作用,还不清楚Oracle对事务的支持到底怎么实现的。下面从物理结构上讲述Oracle怎么对事务进行支持。请先看一个物理结构图。图源自于Oracle Database 10g: Administration Workshop I为了简化,我只是用个人的语言讲述和事务有关的部件。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实现的理解,有不当之处也希望指出,我可以完善文章在Oracle数据库中,提供了一种被称为“事务”的控制机制。通过事物,能够完成对数据有效安全的修改操作,使数据库中的数据达到一个数据一致的状态。举个简单的例子,现在有一个借书系统中设涉及到两张表,一张是图书库存表,一张是用户借书情况表。在用户借书的时候,数据库需要进行两个操作,一是从图书库存表中扣掉库存;另一个操作时在用户借书表中加入这个借书操作。数据库在操作时,往往是先扣减库存,然后再在用户借书情况表中加入借书纪录。假设用户在借书的时候,第一步操作成功,即已经从图书库存表中扣除了某书的库存;但是,在第二步时由于发现用户借的书已经超量或者发现用户的卡中还有罚款不能够借书时,借书就会不成功。若没有事务做控制的话,很明显图书库存就会不准。而在事务的管理下,当第二步不成功的话,第一步操作就会发生回滚。也就是说,事务可以把数据库的好几个操作步骤当作一个整体,当其中有某个操作没有成功的话,则所有操作都会发生回滚。Oracle数据库就是通过这种机制来保障数据的一致性问题。但是,事务若编写的不好的话,则不但起不到应有的作用,还会大大降低数据库的性能。如在数据库事务执行时间比较长,就很有可能导致锁冲突,从而降低数据库的并发访问性能。所以,数据库管理员在编写事务时,还是需要遵守几个指导方针。指导方针一:在事务中尽量使得访问的纪录最小。在事务中,若执行Update等记录操作语句,数据库为了保障数据的一致性,会对其所访问的记录加锁,防止在同一时间内其他用户对其修改。此时,若其他用户需要访问加锁的记录,则必须等待。此时就会发生锁冲突。所以,在事务中要尽量使得访问的记录量最小。如此就可以减少锁定的行数,从而减少事务之间的冲突。这要求数据库管理员在事务中尽量精确的定位语纪录。如在数据库中读取记录时,最好能够使用Where语句进行定位。并且在编写Where语句的时候,要尽量的详细,最好能够实现一对一,则是最好的。如在库存盘点的时候,事务处理语句需要从数据库中读取一定数量的记录,并且为这些记录进行加锁。此时,若记录读取的过多的话,就会对其他用户访问表中的记录造成麻烦。为此,数据库管理员应该建议应用前台应用程序在开发的过程中,加入一些限制条件。如按照产品的分类来更新库存。如此的话,就可以减少一个事务一次性读取的记录数量,从而把锁的影响降低到最低。指导方针二:保持事务尽可能的简洁。在事务中尽量使得访问的纪录最小,这是从数量的角度来考虑锁冲突。而保持事务尽可能的简洁,则是从时间的角度来考虑避免锁冲突的事情。保持事务尽可能的简洁,主要是要求数据库管理员在编写事务的时候,不要把事务写的太过于庞大与复杂。否则,事务在执行的时候就会占用比较多的时间。而这直接导致的后果就是数据库会把某些记录、甚至一张数据表锁住比较长的时间。这就会恶化锁对数据库的负面影响。故当用户在知道了必须要进行修改的记录之后,就要马上启动事务;并且在最短时间内执行完相关的修改语句,然后立即递交或者回滚。而且,只有在确实需要时,才打开事务语句。具体的来说,数据库管理员在事务的简洁性方面,可以尝试如下方法。一是在同一个事务中不要加入过多的修改或者删除语句。如当用户需要更新用户信息表中的相关数据。例如在员工的编号前加入YG前缀并且同时根据员工入职年份计算员工工龄。这两个更新语句若从技术上来说,放在同一个事务中并没有什么不妥。但是,当员工数量比较多时,若把他们合并在一起,则这个事务执行得时间会比较久。为此,最好在更新数据库表的时候,若预计执行时间会比较长,则最好能够把更新语句进行分割,如一列列更新等等二是在更新时,若一次性更新的语句比较多,最好能够选择合适的时候更新。更新某个数据库中记录,其执行所需要的时间往往跟数据库的记录成正比。其记录越多,更新所需要的时间越多。为此,笔者建议,当需要更新的记录比较多的时候,最好能够选择合理的时机。如有些应用程序在设计时,可以把这个更新放在后台处理。如此的话,应用程序就可以选择数据库比较空的时候,来更新表中的记录。这无疑可以在很大程度上降低事务对数据库的负面影响。指导方针三:不要在事务处理期间要求用户输入。数据库管理员在编写事务时,要确保在事务启动之前,让数据库系统获得事务执行所需要的所有内容。如记录的查询条件、所需要更新的内容等等。如果在事务执行的过程中还需要用户的输入,就回滚当前的事务。当用户提供了必要的参数之后,再重新启动这个事务。因为即使在事务执行的过程中,用户立即响应。但是,用户的反应速度要比电脑的响应速度慢的多。所以,当用户在事务执行的过程中需要输入参数的话,就会使得这个事务所占用的数据库资源要保持很长的时间。这就有可能增加阻塞的风险。因为当用户没有及时输入所需要的参数时,事务仍然会保持活动状态,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年销售团队季度目标制定指南
- 物业公共设施维护管理办法
- 法律文书申请书写作模板合集
- 高处作业吊篮安装拆卸工岗位操作规程考核试卷及答案
- 小学二年级下册数学口算训练题选
- 物料索道操作工基础考核试卷及答案
- 塑料焊工基础考核试卷及答案
- 矿车修理工协同作业考核试卷及答案
- 海岸带隧道工程影响评价分析
- 显示器件流程变革分析报告
- 2025年度反洗钱阶段考试培训试考试题库(含答案)
- 收割芦苇施工方案
- 辽宁省沈阳市2025-2026学年七年级上学期第一次月考数学试卷(含答案)
- 小学生日常行为规范知识竞赛试题(附答案)
- 2025年食品安全员考试题库及答案
- 民宿入住免责协议书范本
- 岭南版小学美术四年级上学期教学进度计划
- 管廊运维招聘题库及答案
- 人教版部编三年级上册道德与法治一课一练(含答案)
- (高清版)《建筑施工作业劳动防护用品配备及使用标准》JGJ184-2009
- 全国BIM大赛一等奖获奖项目参赛PPT(76页)
评论
0/150
提交评论