事务并发控制、隔离级别及JDBC事务

1. DBMS事务并发控制  
    1.1 事务并发操作的问题  
       DMBS允许东西运行多个事务,这些事务可能同时操作同一数据对象。这可能造成以下问题
       丢失修改 : 一个事务的修改被另一个事务覆盖。
       不可重复读 : 在一个事务中执行相同的查询,两个的结果不一样。
       幻读 : 幻读是不可重复多的一种,在一个事务中执行相同的查询,第二次的结果行比第一次少或者多(行被delete或者被insert)
       脏读 : 一个事务读到的数据无效的,是另外一个事务回滚的数据

       所以需要对事务进行并发控制,采用的主要技术是锁。

     1.2 锁  
       锁是指一个事务对每个数据对象进行操作时,需要对数据对象加对应锁。这样其他事务最此数据对象访问就受限。当操作结束后事务释放此锁。
        1.2.1 锁的粒度  
         锁的粒度包括逻辑单元也可以是逻辑单元:
         列值(注意不是列)、列值集合、行、表、索引项、整个索引、数据库;
         也可以是物理单元:
         数据页、索引页、块。
         事务可以对各种类型的数据对象加锁,即多粒度加锁。这样在DBMS中就存在了可以被加锁的数据对象树,简称多粒度树。如下,三级多粒度树。
 


        1.2.2 锁的类型  
         锁分为5中类型,如下
         排他锁(X锁):
               也叫写锁。若事务T对数据对象A添加X锁,则只允许T读取和修改A,其他任何事务都不能再对A添加任何类型的锁,直到T释放此锁。
         共享锁(S锁):
               也叫读锁。若事务T对数据对象A添加此类型锁,则事务T允许读取A但不允许修改A,其他事务只能再对A添加S锁,而不能加X锁,直到A上的所有S锁都被释放。
         意向排他锁(IX锁):
               如果对一个数据对象加IX锁,表示他在多粒度树中的后裔(包括直接孩子,孩子的孩子等等所有的后面的结点)有被加X锁的可能(意向)。
         意向共享锁(IS锁):
               如果对一个数据对象加IS锁,表示他在多粒度树中的后裔(包括直接孩子,孩子的孩子等等所有的后面的结点)有被加S锁的可能(意向)。
         共享意向排他锁(SIX):
               如果对一个数据对象加SIX锁,则表示对他加S锁,再加IX锁。

         这个5类锁的相容矩阵如下, T1已经对数据对象加锁,T2尝试对数据对象加锁。Y表示成功,N表示失败。
 

         在Oracle中上面五个类型的锁分别对应X锁、S锁、RX锁、RS锁、SRX锁,而且加锁粒度包括行级和表级,不包括数据库。

         1.2.3锁协议  
         对数据对象加锁时,需要约定一些规则,例如合适申请、持锁时间、何时释放。这些规则称为锁协议。DBMS遵循哪些协议要看具体情况。下面介绍一些协议:
         基本锁协议:当事务T对数据对象A加锁时,如果A上已经存在锁且和T欲加锁不相容, 那么T对待,直到A上存在的所被释放。
         一级锁协议:事务T在修改数据对象A之前必须先对其加X锁,知道事务结束才释放。
         二级锁协议:在一级锁协议的基础上加上事务T在读取数据对象A之前必须先对其加S锁,读完后即可释放S锁。
         三级锁协议:在一级锁协议的基础上加上事务T在读取数据对象A之前必须先对其加S锁,直到事务结束才释放。
         多粒度锁协议: 多粒度树中的每个结点被独立地加锁(显式锁)。对一个结点加锁意味着其所有后裔结点也被加以同样类型的锁(隐式锁, 并没有真正在后裔结点加锁,只是在逻辑上后裔结点具有同样类型的锁,所以叫隐式锁。)。显式锁和隐式锁的效果是一样的,因此检查锁相容时不仅要检查显式锁还要检查隐式锁。所以事务T要对数据对象A加锁,需要检查其祖先(包括直接的和间接的所有上层结点)上的显式锁(检查A的隐式锁是否与欲加的显式锁不相容)、检查其显式锁(检查A已存在的显式锁是否与欲加的显式锁不相容)、检查其后裔的显式锁(检查欲加给后裔的隐式锁是否与后裔已存在的显式锁不相容),如果发现一个不相容锁,则T等待。
         意向锁协议:对任一结点加锁时,必须先对其祖先(包括直接的和间接的所有上层结点)加意向锁,顺序为自上而下。释放结点上锁后,释放其祖先上的意向锁,释放顺序为自下而上。意向锁的含义是如果对一个结点加意向锁,则说明该结点的后裔结点正在被加锁。所以事务T要对数据对象A加锁,需要检查A祖先上的所有锁(检查祖先上的锁是否与欲加给祖先的意向锁相容)、检查A上的所有锁(检查A上的锁是否与欲加他的锁相容),如果发现一个不相容锁,则T等待。
        
         多粒度锁协议,在给结点加锁时需要递归检查子结点的显式锁,当子结点很多时,将带来很多的性能开销。意向锁是针对这个问题进行的改进,他将锁在多粒度树间的传递由原来的由上而下变成由下而上,从而提高了性能。Oracle采用了意向锁协议。

2.DBMS事务隔离级别
     2.1 事务隔离级别的说明
 
       上一节讨论的内容是DBMS实现事务并发控制的内容,是DBMS内部问题。那么如何从外面干预DBMS内部的事务并发控制呢? 
       当事务写数据对象时,DBMS使用X锁及其相关锁(例如IX)进行操作,这个过程是固定的,外界无法也无需干预。
       当事务读数据对象时,哪些数据对象应该对此事务可见呢?例如,其他事务已写还未提交的、其他事务已写已提交的,等等。这个应该是可以选择的,也就是 说外界可以干预。DBMS通过事务隔离级别来让事务选择读哪些数据对象。
       可以这样理解,写是严格操作,不允许发生错误,所以其并发控制是最严格的,也是不可选的。而读是宽松的操作,允许出现 不可重复读 、幻读、脏读问题,所以其并发控制是分多个级别的,可以选择相应的级别改变并发度和允许出现的错误。

     2.2 事务隔离级别类型  
        ANSI/ISO SQ92标准定义了如下事务隔离级别: 
        2.2.1未提交读(read uncommitted)
           事务可以读其他事务未提交数据对象。
           潜在问题: 脏读、不可重复读、幻读
           DBMS锁操作 :不加任何锁,直接读任意数据对象。
        2.2.2提交读(read committed)
           事务可以读其他事务已提交数据对象,读完后此数据对象可以被其他事务再读写。
           可能出现的问题: 不可重复读、幻读
           DBMS锁操作(采用意向锁协议) :加S锁,祖先加IS锁,读完后立即释放S锁和祖先的IS锁。
        2.2.3 重复读(repeatabe read) : 
           事务可以读其他事务已提交数据对象,读完后此数据对象不可以被其他事务再写但可以读,直到 此事务结束。
           可能出现的问题: 幻读
           DBMS锁操作 (采用意向锁协议):加S锁,祖先加IS锁。事务结束后释放S锁和祖先的IS锁。
        2.2.4 序列化(seriaizabe):
           事务读之前,其他事务已提交的数据对象对此事务可见,读完后整个多粒度树只读不能写,直到事务结束。所以他严重的降低了事务的并发度,特别是多粒度树很深时,这也是Oracle没有将数据库作为多粒度树根的原因。在此级别下事务完全隔离,就如所有的事务都顺序执行一样。 
           可能出现的问题: 无
           DBMS锁操作 (采用意向锁协议):加S锁,祖先加SIX锁,事务结束后释放S锁和祖先的SIX锁。

     2.3 隔离级别的使用  
         隔离级别是针对事务的。但是也可以配置Session(对应JDBC的Connection)默认的和DBMS全局默认的事务隔离级别。这样创建事务时不指定就采用默认的事务隔离级别。

3. JDBC事务  
   在JDBC中通过Connection执行事务。一个Connection可以执行多个事务。一个事务可以执行多个SQL语句。

    3.1 事务的开启  
   在Connection中,如果不存在事务,那么在执行SQL语句之前自动开启一个事务。如果事务已经存在那么直接使用其执行SQL语句。

    3.2 事务的结束  
   SQL语句完成之后调用Connection的commit或者rollback方法结束当前事务。在执行之后的SQL语句之前自动开启一个新的事务。

    3.3 设置事务的隔离级别  
   在JDBC中不能单独设置事务的隔离级别,只能通过Session(对应Connection)间接设置,通过Connection的setTransactionIsolation方法。调用此方法之后,如果存在当前事务并且改变了Connection的事务隔离级别那么会引起当前事务立刻提交,之后开启的事务将采用此事务隔离级别。

    3.4 SQL语句的完成时间  
   SQL语句的类型不同,其SQL语句完成时间不同。具体如下
   DML, DDL语句:SQL语句执行完成,那么SQL语句就算完成。
   Select语句:查询语句执行完成后返回ResultSet,当调用ResultSet的close方法后SQL语句算完成。
   多结果语句:当SQL语句返回多结果时(例如执行存储过程,批处理),那么SQL语句的完成时间是所以结果的最大者。

    3.5Connection的自动提交模式  
   Connection有个模式叫自动提交,在这种模式下SQL完成后立即调用Connection的commit方法或者rollback方法。这就使每个SQL在独立的事务中执行。自动提交模式模式是开启的。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值