• Oracle事务之一:锁和隔离


       一. 事务概述

          事务管理是数据库处理的核心。数据库既要保证用户能并发地执行事务,还要保证数据库的一致性。

          当第一条可执行的SQL开始执行,就隐形地开始了一个事务,直到遇到下面的几种情况:

          1.Commit:提交事务。

          2.RollBack:回滚。

          3.DDL语句:执行和提交DDL语句结果前首先提交当前所有DML语句,成为隐式提交。

          4.程序正常退出:自动提交。

          5.不正常的程序失败:隐式回滚。

     

    二.事务特性

          事务的四个特性:A(原子性)、C(一致性)、I(隔离性)、D(永久性)。

     

    三.事务隔离级别

          数据库并发的事务会带来以下四个问题:脏读,更新丢失,不可重复读,幻读。

          对于上面这四个问题,可以通过设置不同的隔离级别来避免。

          首先是未提交读。这种并发性最高,但是仍会产生以上四个问题。

          第二种是已提交读。这是Oracle的默认隔离级别,查询语句只能看到已提交的数据。隔离的已提交读能保证在访问特定的行时,该行的数据保持不变。所以,这个级别可以防止脏读和更新丢失。

          第三种是可重复读。保证读一致性。

          最后一种是串行。隔离级别最高,但数据库的并发性受到了很大的限制。对DML操作的数据会放置一个写锁,别的涉及DML的操作不得不等待锁解除。可以避免上面的四个问题,但在现实中不可用。

     

    四.多版本读一致性

        Oracle通过提供多版本来保证一致性,这个是通过撤销段来实现的。

          Oracle默认提供语句级读一致性,也就是说,查询只能看到它开始前已提交的数据,看不到执行过程中提交的数据。

        事务级读一致性就是可以保证在一个事务中的所有查询一致性。在这种情况下,每个事务中的语句都从同一个时间点来看数据,这个时间点就是事务开始时。它可以避免出现不可重复读和幻读。

     

    五.锁的类型

          根据保护的对象不同,Oracle数据库锁可以分为以下几大类:DML锁(data locks,数据锁),用于保护数据的完整性;DDL锁(dictionary locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;内部锁和闩(internal locks and latches),保护数据库的内部结构。

          DML锁的目的在于保证并发情况下的数据完整性,在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。

          当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。TM锁包括了SS、SX、S、X 等多种模式,在数据库中用0-6来表示。不同的SQL操作产生不同类型的TM锁。

          在数据行上只有X锁(排他锁)。在 Oracle数据库中,当一个事务首次发起一个DML语句时就获得一个TX锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行 DML语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后,TX锁被释放,其他会话才可以加锁。

          下面是各种锁。

    行级排他锁(Row Exclusive,简称RX锁)

          当我们进行DML时会自动在被更新的表上添加RX锁,或者也可以通过执行lock命令显式的在表上添加RX锁。在该锁定模式下,允许其他的事务通过DML语句修改相同表里的其他数据行,或通过lock命令对相同表添加RX锁定,但是不允许其他事务对相同的表添加排他锁(X锁)。

    行级共享锁(Row Shared,简称RS锁)

         通常是通过select … from for update语句添加的,同时该方法也是我们用来手工锁定某些记录的主要方法。比如,当我们在查询某些记录的过程中,不希望其他用户对查询的记录进行更新操作,则可以发出这样的语句。当数据使用完毕以后,直接发出rollback命令将锁定解除。当表上添加了RS锁定以后,不允许其他事务对相同的表添加排他锁,但是允许其他的事务通过DML语句或lock命令锁定相同表里的其他数据行。

    共享锁(Share,简称S锁)

         通过lock table in share mode命令添加该S锁。在该锁定模式下,不允许任何用户更新表。但是允许其他用户发出select …from for update命令对表添加RS锁。

    排他锁(Exclusive,简称X锁)

         通过lock table in exclusive mode命令添加X锁。在该锁定模式下,其他用户不能对表进行任何的DML和DDL操作,该表上只能进行查询。

    共享行级排他锁(Share Row Exclusive,简称SRX锁)

         通过lock table in share row exclusive mode命令添加SRX锁。该锁定模式比行级排他锁和共享锁的级别都要高,这时不能对相同的表进行DML操作,也不能添加共享锁。

         这五种模式的TM锁的兼容关系如下表所示(√表示互相兼容的请求;×表示互相不兼容的请求;N/A表示没有锁定请求):

    -

    S

    X

    RS

    RX

    SRX

    N/A

    S

    ×

    ×

    ×

    X

    ×

    ×

    ×

    ×

    ×

    RS

    ×

    RX

    ×

    ×

    ×

    SRX

    ×

    ×

    ×

    ×

    N/A

          从前面的描述中可以看到,我们不仅可以通过发出DML语句的方式,由Oracle自动在表级别上添加TM锁。我们还可以通过发出lock table命令主动地在表级别上添加TM锁,并在该命令中可以指定不同的锁定模式,其命令格式如下所示:

    lock table in [row share][row exclusive]

    [share][share row exclusive][exclusive] mode;

          对Oracle数据库中的各SQL语句所产生的表级锁的情况进行汇总,如下表所示:

    SQL语句

    表锁定模

    允许的表锁定模式

    Select * from ……

    RS

    RS、RX、S、SRX、X

    Insert into ……

    RX

    RS、RX

    Update ……

    RX

    RS、RX

    Delete from ……

    RX

    RS、RX

    Select * from for update

    RS

    RS、RX、S、SRX

    lock table in row share mode

    RS

    RS、RX、S、SRX

    lock table in row exclusive mode

    RX

    RS、RX

    lock table in share mode

    S

    RS、S

    lock table in share row exclusive mode

    SRX

    RS

    lock table in exclusive mode

    X

    RS

        对于通过lock table命令主动添加的锁定来说,如果要释放它们,只需要发出rollback命令即可。

     

     六.我学习中的疑惑和解答

    疑惑:既然已经有了锁,为什么还要有隔离级别?

    解答:在csdn上找到一个答案,地址:http://topic.csdn.net/u/20100713/12/7e6e102e-03f9-420e-81b3-527ab4437792.html

    具体:

    事务隔离级别是并发控制的整体解决方案,其实际上是综合利用各种类型的锁和行版本控制,来解决并发问题。
    锁是数据库并发控制的内部机制,是基础。当然,数据库同时还会利用行版本控制(SQL Server 2005 及以上)来进行并发控制;在数据库内部还使用闩(latch),互斥(mutex)等机制处理内部资源(如,缓存)的并发访问。
    对用户来说,只有当事务隔离级别无法解决一些并发问题和需求时,才有必要在语句中手动设置锁。不适当的设置锁,可能会导致严重的阻塞和死锁。建议,只有在完全了解锁机制的情况下,才可以在语句中手动设置锁,否则应该使用事务隔离级别。

  • 相关阅读:
    应用市场高速下载以及网页端调起APP页面研究与实现
    linux系统下,添加硬盘并挂载到操作系统的shell 脚本范例
    linux系统下,新加硬盘并把现有的/home目录扩容。
    Java打印裴波那契数列
    JAVA排序的方法
    Java语言输出菱形图型
    Oracle中的sql脚本语言中的循环语句介绍
    Oracle存储过程的创建实例和调用实例
    数组常用方法3---新增元素
    数组常用方法2——修改数组元素。
  • 原文地址:https://www.cnblogs.com/colder/p/5736196.html
Copyright © 2020-2023  润新知