oracle-2中commit 详解

博文转自:http://blog.csdn.net/hzhsan/article/details/9719307html

它执行的时候,你不会有什么感受。commit在数据库编程的时候很经常使用,当你执行DML操做时,数据库并不会马上修改表中数据,这时你须要commit,数据库中的数据就马上修改了,若是在没有commit以前,就算你把整个表中数据都删了,若是rollback的话,数据依然可以还原。听 我这么说,你或许感受commit没什么用,其实否则。当你同时执行两条或两条以上的sql语句时,问题就出现了。举一个例子,你去银行转帐,你转的时候 银行的数据库会update你银行帐户里面的数据,同时对另外一我的得帐户也进行update操做。这两个程序都必须所有正确执行,才能commit,不然 rollback。若是只是完成一条,要么你郁闷,要么银行郁闷,第一种状况是,你的帐户的钱没少,转帐人得帐户上的钱多了,银行郁闷了。第二种状况你的 银行帐户的钱少了,他的却没多,你就好郁闷了。Oracle好好学吧!sql不难,plsql努努力也能熬过去,等到优化那,哎!DBA不是那么好当的。 还有就是commit算是显式提交,还有隐式提交,并非,不commit的话,你的所有努力就都白费了。
   这个命令是将数据写到数据库中。若是不执行COMMIT这个命令,那么在你这个session以外的其余session查询的数据是你修改数据以前的数据。而COMMIT以后人家查询的是你修改的数据。你能够打开两个sqlplus比较作一下测试。一目了然。 
commit的提交针对的是:DML
Data Manipulation Language(DML) 须要提交,这部分是对数据管理操做,好比Insert(插入)、Update(修改)、Delete(删除),
Data Definition Language(DDL) 不须要提交,这部分是对数据结构定义,好比 Create(建立)、Alter(修改)、Drop(删除)
 
   oracle的commit就是提交数据(这里是释放锁不是锁表),在未提交前你前面的操做更新的都是内存,没有更新到物理文件中。执行commit从用户角度讲就是更新到物理文件了,事实上commit时尚未写date file,而是记录了redo log file,要从内存写到data物理文件,须要触发检查点,由DBWR这个后台进程来写,这里内容有点多的,若是不深究的话你就理解成commit即为从内存更新到物理文件。锁有不少种,通常咱们关注的都是DML操做产生的,好比insert,delete,update,select...for update都会同时触发表级锁和行级锁 补充:对的,insert之后commit以前是锁表的状态,其余事务没法对该表进行操做。
若是不提交的话,那么这个表就被锁了 
 COMMIT一般是一个很是快的操做,而不论事务大小如何。你可能认为,一个事务越大(换句话说,它影响的数据越多),COMMIT须要的时间就越长。不是这样的。不论事务有多大,COMMIT的响应时间通常都很“平”(flat,能够理解为无高低变化)。这是由于COMMIT并无太多的工做去作,不过它所作的确实相当重要。

  这一点很重要,之因此要了解并掌握这个事实,缘由之一是:这样你就能心无芥蒂地让事务有足够的大小。一种错误的信念认为分批提交能够节省稀有的系统资源,而实际上这只是增长了资源的使用。若是只在必要时才提交(即逻辑工做单元结束时),不只能提升性能,还能减小对共享资源的竞争(日志文件、各类内部闩等)。sql

  分批提交COMMIT的开销存在两个因素:数据库

  显然会增长与数据库的往返通讯。若是每一个记录都提交,生成的往返通讯量就会大得多。编程

  每次提交时,必须等待redo写至磁盘。这会致使“等待”。在这种状况下,等待称为“日志文件同步”(log file sync)。缓存

  为何COMMIT的响应时间至关“平”,而不论事务大小呢?在数据库中执行COMMIT以前,困难的工做都已经作了。咱们已经修改了数据库中的数据,因此99.9%的工做都已经完成。例如,已经发生了如下操做:安全

  已经在SGA中生成了undo块。session

  已经在SGA中生成了已修改数据块。数据结构

  已经在SGA中生成了对于前两项的缓存redo。oracle

  取决于前三项的大小,以及这些工做花费的时间,前面的每一个数据(或某些数据)可能已经刷新输出到磁盘。异步

  已经获得了所需的所有锁。

  执行COMMIT时,余下的工做只是:

  为事务生成一个SCN。若是你还不熟悉SCN,起码要知道,SCN是Oracle使用的一种简单的计时机制,用于保证事务的顺序,并支持失败恢复。SCN 还用于保证数据库中的读一致性和检查点。能够把SCN看做一个钟摆,每次有人COMMIT时,SCN都会增1.

  LGWR将全部余下的缓存重作日志条目写到磁盘,并把SCN记录到在线重作日志文件中。这一步就是真正的COMMIT。若是出现了这一步,即已经提交。事务条目会从V$TRANSACTION中“删除”,这说明咱们已经提交。

  V$LOCK中记录这咱们的会话持有的锁,这些所都将被释放,而排队等待这些锁的每个人都会被唤醒,能够继续完成他们的工做。

  若是事务修改的某些块还在缓冲区缓存中,则会以一种快速的模式访问并“清理”。块清除(Block cleanout)是指清除存储在数据库块首部的与锁相关的信息。实质上讲,咱们在清除块上的事务信息,这样下一个访问这个块的人就不用再这么作了。咱们采用一种无需生成重作日志信息的方式来完成块清除,这样能够省去之后的大量工做(在下面的“块清除”一节中将更全面地讨论这个问题)。

  能够看到,处理COMMIT所要作的工做不多。其中耗时最长的操做要算LGWR执行的活动(通常是这样),由于这些磁盘写是物理磁盘I/O。不过,这里LGWR花费的时间并不会太多,之因此能大幅减小这个操做的时间,缘由是LGWR一直在以连续的方式刷新输出重作日志缓冲区的内容。在你工做期间,LGWR并不是缓存这你作的全部工做;实际上,随着你的工做的进行,LGWR会在后台增量式地刷新输出重作日志缓冲区的内容。这样作是为了不COMMIT等待很长时间来一次性刷新输出全部的redo。

  所以,即便咱们有一个长时间运行的事务,但在提交以前,它生成的许多缓存重作日志已经刷新输出到磁盘了(而不是所有等到提交时才刷新输出)。这也有很差的一面,COMMIT时,咱们必须等待,直到还没有写出的全部缓存redo都已经安全写到磁盘上才行。也就是说,对LGWR的调用是一个同步(synchronous)调用。尽管LGWR自己可使用异步I/O并行地写至日志文件,可是咱们的事务会一直等待LGWR完成全部写操做,并收到数据都已在磁盘上的确认才会返回。

  前面我提升过,因为某种缘由,咱们用的是一个Java程序而不是PL/SQL,这个缘由就是 PL/SQL提供了提交时优化(commit-time optimization)。我说过,LGWR是一个同步调用,咱们要等待它完成全部写操做。在Oracle 10g Release 1及之前版本中,除PL/SQL之外的全部编程语言都是如此。PL/SQL引擎不一样,要认识到直到PL/SQL例程完成以前,客户并不知道这个PL /SQL例程中是否发生了COMMIT,因此PL/SQL引擎完成的是异步提交。它不会等待LGWR完成;相反,PL/SQL引擎会从COMMIT调用当即返回。不过,等到PL/SQL例程完成,咱们从数据库返回客户时,PL/SQL例程则要等待LGWR完成全部还没有完成的COMMIT。所以,若是在PL /SQL中提交了100次,而后返回客户,会发现因为存在这种优化,你只会等待LGWR一次,而不是100次。这是否是说能够在PL/SQL中频繁地提交呢?这是一个很好或者不错的主意吗?不是,绝对不是,在PL/SQ;中频繁地提交与在其余语言中这样作一样糟糕。指导原则是,应该在逻辑工做单元完成时才提交,而不要在此以前草率地提交。

  COMMIT是一个“响应时间很平”的操做,虽然不一样的操做将生成不一样大小的redo,即便大小相差很大或者说不管生成多少redo,但也并不会影响提交(COMMIT)的时间或者说提交所用的时间都基本相同。

 

 

转自:
http://zhidao.baidu.com/question/345732898.html
http://zhidao.baidu.com/question/446956119.html
http://zhidao.baidu.com/question/126448794.html
http://soft.chinabyte.com/database/75/12306575.shtml
相关文章
相关标签/搜索