• Oracle:在Oracle中使用锁进行并发控制


     现在主流的数据库管理系统中,都支持多个事务同时执行,这样提高了数据库管理系统的运行效率。试想如果只允许一个事务运行,而这个事务又需要很长的时间,那么其他的用户必须一直等待该事务结束,效率何其低下。执行不同的事务虽然可以提高性能,但是有可能会破坏数据的完整性,所以我们必须在性能和数据完整性之间进行权衡。那么什么是并发控制呢?并发控制是数据库管理系统协调多个运行事务的行为。首先了解一下,并发控制中经常遇到的三个问题。

      脏读

       我们通过一个products表来解释一下什么是脏读,该products表有一列quantity(数量),现在的值为20。假如现在有两个事务T1和T2,它们都是要更新quantity列,T1将该列值加100,T2将此列减10,但是T1执行失败进行了回滚。我们很容易计算出正确的结果20-10=10,但是如果事务按照以下方式运行,能够得出什么结果?

      时间   事务   步骤                             存储值

      1      T1     读出quantity的值                20

      2      T1      quantity=20+100             120

      3      T1      写入quantity值                  120

      4      T2      读出quantity(T1未提交)     120

      5      T2      quantity=120-10             110

      6      T1      回滚(rollback)                  20

      7      T2      写入quantity值                 110

       以上得出了110的结果,显然是不正确的,问题就在于T2读取到了T1没有提交的数据,我们把这种情况就称之为脏读。

      不可重复读

       还是事务T1和T2,它们都是要更新quantity列,T1将该列值加100,T2将此列减10,而且两个事务都成功。我们很容易计算出正确的结果20+100-10=110,但是如果事务按照以下方式运行,能够得出什么结果?

      时间   事务   步骤                             存储值

      1      T1     读出quantity的值                20

      2      T2     读出quantity的值               20

      3      T1     quantity=20+100                  120

      4      T2     quantity=20-10                  10

      5      T1     写入quantity值(更新丢失)          110

      6      T2     写入quantity值                  10

       得出了10的结果,仍然是不正确的。问题就在于T2的值覆盖了T1的值,我们把这种情况称之为不可重复读。

      幻觉读

       例如T1对一个表中的所有行修改,同时T2向该表中插入一行记录。这时在T1中就会发生还有没有被修改的数据行,就好象发生了幻觉一样。

       SQL92标准定义了四种隔离级别,以解决以上问题,四种隔离级别如下图所示:

      

       Oracle提供了三种隔离级别,分别是Read Committed Serializable和Read Only。Read Committed是Oracle的默认隔离级别,可以看出这种隔离级别消除了脏读,但是避免不了不可重复读和幻觉读的发生,不过一般的应用还是可以使用该隔离级别的。Serializable这种隔离级别可以消除以上三个问题,但是效率会降低很多。Read Only隔离级别不是SQL92标准中定义的,它不允许事务进行更新操作,这种隔离级别也可以消除脏读。

       Oracle中在事务开始之前可以通过以下方式设置隔离级别:

    set transation isolation level read committed;
    set transation isolation level serialezable;
    set transation isolation level read only;

       也可以在单独的会话中设置隔离级别:

    alter session set isolation_level read committed;
    alter session set isolation_level serialezable;
    alter session set isolation_level read only;

       通过刚才的介绍,我们知道了可以设置隔离级别来降低或者消除数据的不完整性,那数据库管理系统是怎么做到这一点的呢?答案是,采用锁。锁可以保护数据,当一个事务修改数据时,锁会将该数据锁定,防止这些数据在同一时刻被其它事务修改。

       大多数情况下,我们可以不必自己管理锁,Oracle会自动创建并管理,但是了解锁是如何工作的,对我们来说也是非常有必要的。下列这些情况Oracle会创建锁:

       当我们运行了create truncate alter语句时,Oracle会创建锁,称之为DDL锁。

       当我们运行了insert update delete语句,Oracle会创建锁,称之为DML锁。

       还有一种是内部锁,由Oracle在内部使用,比如管理数据文件。在这里我们不做介绍。

       从级别上讲,锁还可以分为数据库级别锁、表级别锁、行级别锁和列级别锁(Oracle不支持)。

      1、数据库级别锁:它会锁定数据库以禁止任何新会话和新事务。锁定数据库的最主要目的是在没有用户干扰的情况下完成维护。在Oracle中使用以下语句锁定数据库为限制模式:

    alter system enable restricted session;

      通过下列语句取消数据库限制模式:

    alter system disable restricted session;

      以下语句将锁定数据库为只读模式:

    startup mount;
    alter database open read only;

      2、表级别锁:它会锁定整张表,以防止其它事务对表结构进行修改。比如当我们运行一个insert语句,如果表没有没锁定,其它的事务修改了一列(将列名修改),这时我们运行update语句就会出错,所以当我们运行DML语句时,Oracle会自动将表锁定,DML语句执行完,会释放表级别锁。我们也可以通过lock语句锁定表。

      3、行级别锁:当我们运行DML语句时,当前行上就会有行级别锁,防止其它事务对该行进行修改。

      当我们运行DML语句时,Oracle会自动加锁,请看以下示例:

      update dept set loc='北京' where deptno=40;

      然后在Oracle的企业管理器中观察Oracle自动管理的锁,如下图:

      从上图中我们可以看到,我们运行了一个update语句,产生了两个锁,都是scott用户,SID表示会话是10,锁类型TM表示表级别锁,而TX表示行级别锁,占用的模式我们后面给大家介绍。

      

      锁类型:TM 锁模式:share    某个事务锁定了一张表,允许其它事务再锁定这张表,但不允许这个事务对这张表进行更新。

      锁类型:TM 锁模式:row share 某个事务锁定了一张表,允许其它事务再锁定这张表中的其它行。

      锁类型:TM 锁模式:row eclusive 某个事务锁定了一张表,允许其它事务以相同的锁模式锁定这张表。

      锁类型:TM 锁模式:share row eclusive 在share模式基础上,不允许其它事务锁定这张表。

      锁类型:TM 锁模式:eclusive  不允许其它事务再锁定该表,也不允许其它事务更新。

      锁类型:TX 锁模式:eclusive  该行已经被锁定,不允许其它事务锁定。

  • 相关阅读:
    浅议APC
    fastIO
    设备对象 驱动对象
    PostMessage和SendMessage的区别
    使用DLL在进程间共享数据
    32位程序读写64位程序内存
    windows文件映射
    windows消息传送(自定义消息和WM_COPYDATA)
    windows剪贴板
    mysql innobackupex备份工具
  • 原文地址:https://www.cnblogs.com/tracy/p/2182408.html
Copyright © 2020-2023  润新知