• 04 关于oracle的锁的级别以及介绍


    关于oracle的锁的级别以及介绍

    oracle造成锁表的情况:

    一、查看锁的对象视图:select object_id,session_id,locked_mode from v$locked_object;

    二、0:none 1:null 空  2:Row-S 行共享(RS):共享表锁 3:Row-X 行专用(RX):用于行的修改 4:Share 共享锁(S):阻止其他DML操作 5:S/Row-X 共享行专用(SRX):阻止其他事务操作  6:exclusive 专用(X):独立访问使用 。

    常用的sql会造成锁表:

    1、select ... from ... for update; 是2的锁。

    2、insert / update / delete .(DML).. ; 是3的锁。

    3、创建索引的时候也会产生3,4级别的锁。

    4、主外键约束时 update / delete ... ; 可能会产生4,5的锁。

    5、DDL(alter,drop)语句可能会产生时是6的锁。

    在锁定中,存在以下两种基本的模式。

    排他锁(Exclusive,简称X锁):一旦用户对某个资源添加了X锁,则其他用户都不能再对该资源添加任何类型的锁,直到该用户释放了资源上的X锁为止。

    共享锁(Share,简称S锁):一旦用户对某个资源添加了S锁,则其他用户都不能在该资源上添加X锁,只能添加S锁,直到该用户释放了资源上的S锁为止。

    根据被保护的对象种类的不同,锁定可以分成多种类型,比如由于DDL引起的锁定、DML事务引起的锁定、分布式事务中涉及的锁定等。我们主要应该关注DML事务引起的锁定。

    10.3  DML事务锁定的机制  

    锁定能够保证当某个用户正在更新表里的一行数据时,其他用户不能同时更新相同的数据行,而且也不能删除或修改被更新的表。

    锁定分为两种级别:行级别(TX锁)和表级别(TM锁)。

    10.3.1  行级锁(TX锁) 

    假设某个用户(假设为A)发出如下的语句更新一条记录:

    SQL> update employees set last_name='HanSijie' 
    where employee_id=100;

    Oracle在对该SQL进行解析以后,找到employee_id为100的记录所在的数据块(假设为58号数据块),并找一个可用的undo数据块,将last_name列上被更新前的旧值放入该undo数据块,然后在数据块头部分配一个ITL槽,在该ITL槽里存放当前的事务ID号、SCN号、所使用的undo数据块的地址,以及当前还未提交的标记等信息。接下来,在58号数据块中,找到被更新的数据行,在其头部设置一个锁定标记,并在头部记录当前事务所使用的ITL槽的槽号。做完这些工作以后,将控制权(也就是光标)返回给用户。该锁定标记说明当前用户在被修改的数据行上已经添加了X锁。

    如果这时,另一个用户(假设为N)也对employee_id为100的记录进行修改,则其过程和上面描述的一样,只不过B在对数据行的头部设置锁定标记时,发现该数据行头部已经有一个锁定标记了,说明该记录已经被添加了X锁,于是用户进程N必须等待,等待该X锁被释放。

    可以看到,Oracle数据库是在物理层面上实现对数据行的锁定问题。而且锁定一条记录,并不影响其他用户对该记录的读取。比如,如果当前有一个用户(假设为C)发出SQL语句,检索employee_id为100的记录信息,这时服务器进程发现被检索的记录有锁定标记,说明当前该记录已经被其他用户修改了,但是还没提交。于是根据数据行头部记录的ITL槽的槽号,在数据块头部找到该ITL槽,并根据其中记录的undo数据块的地址,找到该undo数据块,将其中所保存的改变前的旧值取出,并据此构建CR(Consistent Read一致性读)块,该CR块中的数据就是被更新的数据块(也就是58号数据块)在更新前的内容。于是根据该CR块的内容,将用户所需要的信息返回给C。

    对于Oracle数据库来说,行级锁只有X锁定模式,没有S锁定模式。Oracle的锁定总是尽可能地在最低级别上完成。比如更新数据行时,仅仅是锁定被更新的数据行,并不会锁定同一个数据块中的其他数据行,也不会阻塞其他用户查询被更新的数据行。

    10.3.2  表级锁(TM锁) 

    还是接着上面的例子,这时A用户已经发出了更新employee_id为100的记录的SQL语句。当A还没有提交之前,另外一个用户D发出下面的语句:

    SQL> drop table employees;

    由于用户A还没有提交所做的事务,因此该事务还没有结束,其他用户还不能删除该表,否则A所发出的事务就无法正常结束。为了阻止这时用户D的删除操作,我们能够想到的最直观的方法就是,在执行删除表的命令之前,先依次检查employees表里的每一条记录,查看每一条数据行的头部是否存在锁定标记,如果是,则说明当前正有事务在更新该表,删除表的操作必须等待。

    显然,这种方式会引起很大的性能问题,Oracle不会采用这种方式。实际上,当我们在对employees表的数据进行更新时,不仅会在数据行的头部记录行级锁,而且还会在表的级别上添加一个表级锁。那么当D用户要删除表时,发现employees表上具有一个表级锁,于是等待。

    通过这种在表级别上添加锁定的方式,我们就能够比较容易并且高效地(因为不需要扫描表里的每一条记录来判断在表上是否有DML事务)对锁定进行管理了。表级锁共具有五种模式,如下所示。

    行级排他锁(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命令即可。

  • 相关阅读:
    这才是世上最全的“软件测试”思维导图!
    Scrum3.0 敏捷开发白皮书
    敏捷软件质量保证的方法与实践
    C# DataGridView 列的显示顺序
    Xamarin.android 重写axml控件
    Xamarin控件使用之GridView
    Sql 的 RAISERROR用法
    Xamarin.Android 怎么定义一个按钮和返回键功能一样回到上一个界面
    Xamarin.android Activity动画切换效果实现
    Xamarin.Android之封装个简单的网络请求类
  • 原文地址:https://www.cnblogs.com/jason01/p/9182743.html
Copyright © 2020-2023  润新知