读取数据事务

最近研究读取数据,稍微总结一下,以后继续补充:

     事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个弗成分割的工作单位。例如,银行转账工作:从一个账号扣款并使另一个账号增款,这两个操作要么都执行,要么都不执行。所以,应该把它们看成一个事务。事务是数据库维护数据一致性的单位,在每个事务结束时,都能坚持数据一致性。

    

    

       针对下面的描述可以看出,事务的提出重要是为了处理并发情况下坚持数据一致性的问题。

    

       事务拥有以下4个基本特征。

    

●   Atomic(原子性):事务中包括的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全体成功,要么全体失败。

    

●   Consistency(一致性):只有合法的数据可以被写入数据库,否则事务应该将其回滚到最初状态。

    

●   Isolation(断绝性):事务答应多个用户对同一个数据进行并发拜访,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。

    

●   Durability(速决性):事务结束后,事务处置的结果必须能够得到固化。

    

       数据库肯定是要被广大客户所同享拜访的,那么在数据库操作进程中很可能出现以下几种不确定情况。

    

●   更新丧失(Lost update):两个事务都同时更新一行数据,但是第二个事务却半途失败退出,导致对数据的两个修改都失效了。这是因为系统没有执行任何的锁操作,因此并发事务并没有被断绝开来。

    

●   脏读取(Dirty Reads):一个事务开始读取了某行数据,但是另外一个事务已更新了此数据但没有能够及时提交。这是相称危险的,因为很可能所有的操作都被回滚。

    

●   弗成重复读取(Non-repeatable Reads):一个事务对同一行数据重复读取两次,但是却得到了不同的结果。例如,在两次读取的半途,有另外一个事务对该行数据进行了修改,并提交。

    

●   两次更新问题(Second lost updates problem):没法重复读取的特例。有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交。这就会造成第一次写操作失效。
    每日一道理
“一年之计在于春”,十几岁的年纪,正是人生的春天,别辜负了岁月老人的厚爱与恩赐。行动起来,播种梦想吧!

    

●   虚读(Phantom Reads):事务在操作进程中进行两次查询,第二次查询的结果包括了第一次查询中未出现的数据(这里并不要求两次查询的SQL语句相同)。这是因为在两次查询进程中有另外一个事务插入数据造成的。

    

 数据库的断绝级别
       为了避免下面出现的几种情况,在标准SQL标准中,定义了4个事务断绝级别,不同的断绝级别对事务的处置不同。
●   未授权读取(Read Uncommitted):答应脏读取,但不答应更新丧失。如果一个事务已开始写数据,则另外一个数据则不答应同时进行写操作,但答应其他事务读此行数据。该断绝级别可以通过“排他写锁”实现。
●   授权读取(Read Committed):答应弗成重复读取,但不答应脏读取。这可以通过“霎时同享读锁”和“排他写锁”实现。读取数据的事务答应其他事务继续拜访该行数据,但是未提交的写事务将会禁止其他事务拜访该行。
●   可重复读取(Repeatable Read):禁止弗成重复读取和脏读取,但是偶然可能出现幻影数据。这可以通过“同享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但答应读事务),写事务则禁止任何其他事务。
●   序列化(Serializable):供给严厉的事务断绝。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是没法实现事务序列化的,必须通过其他机制保障新插入的数据不会被刚执行查询操作的事务拜访到。
       断绝级别越高,越能保障数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先斟酌把数据库系统的断绝级别设为Read Committed,它能够避免脏读取,而且拥有较好的并发性能。尽管它会导致弗成重复读、虚读和第二类丧失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采取悲观锁或悲观锁来控制。
       通过前面的分析已知道,通过选用不同的断绝品级就能够在不同程度上避免前面所提及的在事务处置中所面对的各种问题。所以,数据库断绝级别的选取就显得尤为重要,在选取数据库的断绝级别时,应该注意以下几个处置的原则:
       首先,必须清除“未授权读取”,因为在多个事务之间使用它将会是非常危险的。事务的回滚操作或失败将会影响到其他并发事务。第一个事务的回滚将会完全将其他事务的操作清除,甚至使数据库处在一个不一致的状态。很可能一个已回滚为结束的事务对数据的修改最后却修改提交了,因为“未授权读取”答应其他事务读取数据,最后整个错误状态在其他事务之间传播开来。
       其次,绝大部分应用都无须使用“序列化”断绝(一般来说,读取幻影数据并非一个问题),此断绝级别也难以丈量。现在使用序列化断绝的应用中,一般都使用悲观锁,这样强行使所有事务都序列化执行。
       剩下的也就是在“授权读取”和“可重复读取”之间选择了。我们先斟酌可重复读取。如果所有的数据拜访都是在统一的原子数据库事务中,此断绝级别将清除一个事务在另外一个并发事务进程中覆盖数据的可能性(第二个事务更新丧失问题)。这是一个非常重要的问题,但是使用可重复读取并非处理问题的独一途径。
       假设使用了“版本数据”,Hibernate会自动使用版本数据。Hibernate的一级Session缓存和版本数据已为你供给了“可重复读取断绝”绝大部分的特性。特殊是,版本数据可以防止二次更新丧失的问题,一级Session缓存可以保障速决载入数据的状态与其他事务对数据的修改断绝开来,因此如果使用对所有的数据库事务采取授权读取断绝和版本数据是行得通的。
       “可重复读取”为数据库查询供给了更好的效率(仅对那些长时间的数据库事务),但是由于幻影读取仍然存在,因此没必要使用它(对于Web应用来说,一般也很少在一个数据库事务中对同一个表查询两次)。
       也可以同时斟酌选择使用Hibernate的二级缓存,它可以犹如底层的数据库事务一样供给相同的事务断绝,但是它可能弱化断绝。假如在二级缓存大批使用缓存并发策略,它并不供给重复读取语义(例如,前面章节中将要探讨的读写,特殊是非严厉读写),很轻易可以选择默认的断绝级别:因为无论如何都没法实现“可重复读取”,因此就更没有必要拖慢数据库了。另一方面,可能对症结类不采取二级缓存,或者采取一个完全的事务缓存,供给“可重复读取断绝”。那么在业务中须要使用到“可重复读取”吗?如果你爱好,当然可以那样做,但更多的时候并没有必要花费这个代价。

文章结束给大家分享下程序员的一些笑话语录: 面试官:熟悉哪种语言
应聘者:JAVA
面试官:知道什么叫类么
应聘者:我这人实在,工作努力,不知道什么叫累
面试官:知道什么是包?
应聘者:我这人实在 平常不带包 也不用公司准备了
面试官:知道什么是接口吗?
应聘者:我这个人工作认真。从来不找借口偷懒
面试官:知道什么是继承么
应聘者:我是孤儿没什么可以继承的
面试官:知道什么叫对象么?
应聘者:知道,不过我工作努力,上进心强,暂时还没有打算找对象。
面试官:知道多态么?
应聘者:知道,我很保守的。我认为让心爱的女人为了自已一时的快乐去堕胎是不道德的行为!请问这和C#有什么关系??

原文地址:https://www.cnblogs.com/xinyuyuanm/p/3076957.html