zoukankan      html  css  js  c++  java
  • 【转载并整理】ORACLE锁机制

    转载文章:http://blog.csdn.net/liuyiy/article/details/25005393

    转载文章:http://www.cnblogs.com/jiyuqi/p/3701716.html

    1.介绍

    数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。

    在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改;加了共享锁的数据对象可以被其他事务读取,但不能修改。

    根据保护对象的不同,Oracle数据库锁可以分为以下几大类:

    (1) DML lock(data locks,数据锁):用于保护数据的完整性;

    (2) DDL lock(dictionary locks,字典锁):用于保护数据库对象的结构(例如表、视图、索引的结构定义);

    (3) Internal locks 和latches(内部锁与闩):保护内部数据库结构;

    (4) Distributed locks(分布式锁):用于OPS(并行服务器)中;

    (5) PCM locks(并行高速缓存管理锁):用于OPS(并行服务器)中。

    在Oracle中最主要的锁是DML(也可称为data locks,数据锁)锁。DML锁的目的在于保证并发情况下的数据完整性。

    在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。

    TM锁(表级锁)类型共有5种,分别称为共享锁(S锁)、排它锁(X锁)、行级共享锁(RS锁)、行级排它锁(RX锁)、共享行级排它锁(SRX锁)

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

    表1 Oracle的TM锁类型

    锁模式

    锁描述

    解释

    SQL操作

    0

    none

     

     

    1

    NULL

    Select

    2

    SS(Row-S)

    行级共享锁,其他对象只能查询这些数据行

    Select for updateLock for updateLock row share

    3

    SX(Row-X)

    行级排它锁,在提交前不允许做DML操作

    InsertUpdateDeleteLock row share

    4

    S(Share)

    共享锁

    Create indexLock share

    5

    SSX(S/Row-X)

    共享行级排它锁

    Lock share row exclusive

    6

    X(Exclusive)

    排它锁

    Alter tableDrop ableDrop indexTruncate table Lock exclusive

    1. 共享锁(Share Table Lock,S):

    加锁语法:Lock Table TableName In Share Mode;

    允许的操作:一个共享锁由一个事务控制,仅允许其它事务查询被锁定的表。一个有效的共享锁明确地用Select … For update形式锁定行,或执行Lock Table TableName In Share Mode语法锁定整个表,不允许被其它事务更新。

    禁止的操作:一个共享锁由一个事务来控制,防止其它事务更新该表或执行下面的语句:

    LOCK TABLE TableName IN SHARE ROW EXCLUSIVE MODE;

    LOCK TABLE TableName IN ROW EXCLUSIVE MODE;

    2. 排它锁(Exclusive Table Lock,X):

    排它锁是在锁机制中限制最多的一种锁类型,允许加排它锁的事务独自控制对表的写权限。

    加锁语法:Lock Table TableName In Exclusive Mode;

    允许的操作:在一个表中只能有一个事务对该表实行排它锁,排它锁仅允许其它的事务查询该表。

    禁止的操作:拥有排外锁的事务禁止其它事务执行其它任何DML类型的语句或在该表上加任何其它类型的锁。

    定义排它锁的语法:

    LOCK TABLE TableName IN EXCLUSIVE MODE;

    3. 行级锁(Row Share Table Lock,RS):

    一个行级锁(有时称为Subshare Table Lock,简称SS,子共享锁)需要该事务在被锁定行的表上用update的形式加锁。当有下面语句被执行的时候行级锁自动加在操作的表上。

    SELECT . . . FROM TableName. . . FOR UPDATE OF . . . ;

    LOCK TABLE TableName IN ROW SHARE MODE;

    行级锁(Row Share Table Lock)在锁类型中是限制最少的,也是在表的并发程度中使用程度最高的。

    允许的操作:行级共享锁由一个事务控制,允许其它事务查询、插入、更新、删除或同时在同一张表上锁定行。因此其它事务可以同时在同一张表上得到行级锁、共享行级排它锁、行级排它锁、排它锁。

    禁止的操作:拥有行级锁的事务不允许其它事务执行排它锁,即:

    Lock Table TableName In Exclusive Mode;

    4. 行级排它锁(Row Exclusive Table Lock,RX):

    行级排它锁(亦称为Subexclusive Table Lock,简称SX,子排它锁)通常需要事务拥有的锁在表上被更新一行或多行。当有下面语句被执行的时候行级排它锁被加在操作的表上。

    INSERT INTO TableName. . . ;

    UPDATE TableName. . . ;

    DELETE FROM TableName. . . ;

    LOCK TABLE TableName IN ROW EXCLUSIVE MODE;

    行级排它锁比行级锁稍微多一些限制。

    允许的操作:行级排它锁由一个事务拥有允许其它事务执行查询、修改、插入、删除或同时在同一张表上锁定行。执有行级排它锁的事务允许其它事务在同一张表上同时得到共享锁和行级排它锁。

    禁止的操作:行级排它锁由一个事务拥有防止其它事务手动锁定表来排除其它事务的读写权。因此,其它事务不允许在同一张表上使用以下的语句来执行锁事务。

    LOCK TABLE table IN SHARE MODE;

    LOCK TABLE table IN SHARE EXCLUSIVE MODE;

    LOCK TABLE table IN EXCLUSIVE MODE

    5. 共享行级排它锁(Share Row Exclusive Table Lock,SRX):

    共享行级排它锁有时也称共享子排它锁(Share Subexclusive Table Lock,SSX),它比共享锁有更多限制。定义共享行级排它锁的语法为:

    Lock Table TableName In Share Row Exclusive Mode;

    允许的操作:仅允许一个事务在某一时刻得到行级排它锁。拥有行级排它锁事务允许其它事务在被锁定的表上执行查询或使用Select … From TableName For update…来准确在锁定行而不能更新行。

    禁止的操作:拥有行级排它锁的事务不允许其它事务有除共享锁外的其它形式的锁加在同一张表上或更新该表。即下面的语句是不被允许的:

    LOCK TABLE TableName IN SHARE MODE;

    LOCK TABLE TableName IN SHARE ROW EXCLUSIVE MODE;

    LOCK TABLE TableName IN ROW EXCLUSIVE MODE;

    LOCK TABLE TableName IN EXCLUSIVE MODE;

    当Oracle数据库发生TX锁等待时,如果不及时处理常常会引起Oracle数据库挂起,或导致死锁的发生,产生ORA-60的错误。

     2.锁相关的视图

    TX锁等待的分析

    Oracle数据库中一般使用行级锁。

    Oracle检测到死锁产生时,中断并回滚死锁相关语句的执行,报ORA-00060的错误并记录在数据库的日志文件alertSID.log中。同时在user_dump_dest下产生了一个跟踪文件,详细描述死锁的相关信息。

    在日常工作中,如果发现在日志文件中记录了ora-00060的错误信息,则表明产生了死锁。这时需要找到对应的跟踪文件,根据跟踪文件的信息定位产生的原因。

    数据字典视图说明

    视图名

    描述

    主要字段说明

    v$session

    查询会话的信息和锁的信息。

    sid,serial#:表示会话信息。

    program:表示会话的应用程序信息。

    row_wait_obj#:表示等待的对象,和dba_objects中的object_id相对应。

    v$session_wait

    查询等待的会话信息。

    sid:表示持有锁的会话信息。

    Seconds_in_wait:表示等待持续的时间信息

    Event:表示会话等待的事件。

    v$lock

    列出系统中的所有的锁。

    Sid:表示持有锁的会话信息。

    Type:表示锁的类型。值包括TMTX等。

    ID1:表示锁的对象标识。

    lmode,request:表示会话等待的锁模式的信

    息。用数字06表示,和表1相对应。

    dba_locks

    v$lock的格式化视图。

    Session_id:和v$lock中的Sid对应。

    Lock_type:和v$lock中的type对应。

    Lock_ID1 v$lock中的ID1对应。

    Mode_held,mode_requested:和v$lock

    lmode,request相对应。

    v$locked_object

    只包含DML的锁信息,包括回滚段和会话信息。

    Xidusn,xidslot,xidsqn:表示回滚段信息。和

    v$transaction相关联。

    Object_id:表示被锁对象标识。

    Session_id:表示持有锁的会话信息。

    Locked_mode:表示会话等待的锁模式的信

    息,和v$lock中的lmode一致。

    解锁及Kill Session:

    使用下面的语法查出锁并杀掉Session。

    SELECT A.SID,A.SERIAL#,A.USERNAME,B.TYPE FROM V$SESSION A,V$LOCK B WHERE A.SID=B.SID;

    ALTER SYSTEM KILL SESSION 'SID,SERIAL#';

    v$lock
     
    SID          会话的sid,可以和v$session 关联    
    TYPE         区分该锁保护对象的类型,如tm,tx,rt,mr等 
    ID1          锁表示1,详细见下说明                 
    ID2          锁表示2,详细见下说明            
    LMODE        锁模式,见下面说明              
    REQUEST      申请的锁模式,同lmode                  
    CTIME        已持有或者等待锁的时间                 
    BLOCK        是否阻塞其他会话锁申请 1:阻塞 0:不阻塞 <br><br>

    LMODE取值0,1,2,3,4,5,6, 数字越大锁级别越高, 影响的操作越多。  

    1级锁:  Select,有时会在v$locked_object出现。  

    2级锁即RS锁,相应的sql有:Select for update ,Lock xxx in  Row Share mode,select for update当对话使用for update子串打开一个游标时,所有返回集中的数据行都将处于行级(Row-X)独  占式锁定,其他对象只能查询这些数据行,不能进行update、delete或select for update操作。  

    3级锁即RX锁,相应的sql有:Insert, Update, Delete, Lock xxx in Row Exclusive mode,没有commit之前插入同样的一条记录会没有反应, 因为后一个3的锁会一直等待上一个3的锁, 我们必须释放掉上一个才能继续工作。  

    4级锁即S锁,相应的sql有:Create Index, Lock xxx in Share mode  

    5级锁即SRX锁,相应的sql有:Lock xxx in Share Row Exclusive mode,当有主外键约束时update/delete ... ; 可能会产生4,5的锁。  

    6级锁即X锁,相应的sql有:Alter table, Drop table, Drop Index, Truncate table, Lock xxx in Exclusive mode  

    ID1,ID2的取值含义根据type的取值而有所不同  

    对于TM 锁,ID1表示被锁定表的object_id 可以和dba_objects视图关联取得具体表信息,ID2 值为0  

    对于TX 锁,ID1以十进制数值表示该事务所占用的回滚段号和事务槽slot number号,其组形式:  0xRRRRSSSS,RRRR=RBS/UNDO NUMBER,SSSS=SLOT NUMBER  

    ID2 以十进制数值表示环绕wrap的次数,即事务槽被重用的次数

    v$locked_object 
     
    XIDUSN               undo segment number , 可以和v$transaction关联     
    XIDSLOT              undo slot number       
    XIDSQN               序列号                          
    OBJECT_ID            被锁定对象的object_id ,   可以和dba_objects关联 
    SESSION_ID           持有该锁的session_id,     可以和v$session关联 
    ORACLE_USERNAME      持有该锁的oracle帐号                      
    OS_USER_NAME         持有该锁的操作系统帐号                       
    PROCESS              操作系统的进程号,可以和v$process关联       
    LOCKED_MODE          锁模式,含义同v$lock.lmode 
       
    Dba_locks 和v$lock 内容差不多,略 
       
    V$session           如果某个session被因为某些行被其他会话锁定而阻塞,则该视图中的下面四个字段列出了这些行所属对象的相关信息 
    ROW_WAIT_FILE#      等待的行所在的文件号 
    ROW_WAIT_OBJ#       等待的行所属的object_id 
    ROW_WAIT_BLOCK#     等待的行所属的block 
    ROW_WAIT_ROW#       等待的行在blcok中的位置

    3. oracle中锁的检测及解锁

    --查看被锁的表
    SELECT
      p.spid, a.serial#, c.object_name, b.session_id, b.oracle_username,b.os_user_name
    FROM
      v$process p, v$session a, v$locked_object b, all_objects c
    WHERE
      p.addr = a.paddr
    AND
      a.process = b.process
    AND
      c.object_id = b.object_id;
            
    --查看锁表的进程
    select
      b.sid,b.serial#
    from
      v$locked_object a,v$session b
    where
      a.session_id = b.sid
    group by
      b.sid,b.serial#;
     
    --单个删除锁表的进程
    alter system kill session '36,32435'
     
    --批量删除锁表的进程
    declare cursor
        mycur
    is
    select
        b.sid,b.serial#
    from
        v$locked_object a,v$session b
    where
        a.session_id = b.sid
    group by
        b.sid,b.serial#;
    begin
      for cur in mycur
        loop
          execute immediate ( 'alter system kill session '''||cur.sid || ','|| cur.SERIAL# ||''' ');
        end loop;
    end;
  • 相关阅读:
    C++笔记(2018/2/6)
    2017级面向对象程序设计寒假作业1
    谁是你的潜在朋友
    A1095 Cars on Campus (30)(30 分)
    A1083 List Grades (25)(25 分)
    A1075 PAT Judge (25)(25 分)
    A1012 The Best Rank (25)(25 分)
    1009 说反话 (20)(20 分)
    A1055 The World's Richest(25 分)
    A1025 PAT Ranking (25)(25 分)
  • 原文地址:https://www.cnblogs.com/yingsong/p/7645965.html
Copyright © 2011-2022 走看看