首页 > 其他 > 详细

事务与锁定

时间:2015-02-08 23:24:25      阅读:567      评论:0      收藏:0      [点我收藏+]

DML(DATA MANIPULATION LANGUAGE):INSERT,UPDATE,DELETE,MERGE
DDL(DATA DEFINITION LANGUAGE):CREATE,ALTER,DROP
DCL(DATA CONTROL LANGUAGE):授于或回收访问数据库的某种特权

一个事务开始于一条执行的SQL语句,结束于:
    1.用户提交事务
    2.用记回滚事务
    3.遇到DDL语句
    4.遇到DCL语句
    5.用户结束会话
    6.数据库关闭或系统崩溃
显式回滚:
    ROLLBACK    //可以指定回滚到事务中的一个位置,这个位置叫做保存点
显式提交:
    COMMIT;

事务自动提交:
    1.执行DDL语句
    2.执行DCL语句
    3.正常结束会话
系统自动回滚事务
    1.异常结束会话
    2.数据库关闭或系统崩溃
    

当事务要对指定的数据块进行读取,修改或删除操作之前,它需要确保这些数据块不会同时被其他事务所修改,可以通过锁定数据块的方式禁止其他事务修改指定数据块

通常事务的开始和结束决定了锁的锁定和释放时间
操作类型不同,锁的粒度和强度也不同

活锁:指程序无限期等待。解决方法是先来先服务策略。

死锁:是指两个或多个事务都锁定了一些数据库对象,然后又需要锁定对方的数据库对象而且失败需要等待造成的。即相互等待对方锁定的资源释放。

预防死锁的方法有:一次锁定、顺序锁定(这是操作系统的解决方法,但不适用数据库)。

 常用解决数据库死锁的方法是先诊断后解除。其方法有两种:超时法、等待图法。

超时法:即如果事务的等待时间超过了规定的时限,就认为发生了死锁。缺点是:容易误判死锁;时限不好决定;

等待图法:事务的等待图是一个有向图,如果事务T1等待事务T2,则T1和T2节点之间就有一条从T1指向T2的有向边。如果T1和T2之间产生回路就说明发生了死锁。

解决死锁的常用方法是:手动地选择一个处理死锁的代价最小的事务,将其撤销,使其释放所有已锁定的数据库对象。



锁定数据库的两种方式:

1、 将数据库设置成受限制方式;2、将数据库更改为只读方式;

ORACLE锁的级别

    数据库级别锁、表级别锁、行级别锁。不支持列级别锁。


锁的类型:
    1.排他锁(EXCLUSIVE LOCK X锁):防止并发事务对资源的写操作,在执行INSERT,UPDATE,DELETE时使用,排他锁与其他任何类型的锁都不兼容

    2.共享锁(SHARE LOCK    S锁):用于并发执行对一个数据资源的读取操作,使用SELECT语句时可以使用共享锁,当有共享锁时,任何事务都不能修改该资源数据,读取完后,共享锁被释放,共享锁与共享锁兼容,与排他锁不兼容
        
    3.DDL锁(字典锁):当用户使用DDL语句时,ORACLE会自动对DDL语句涉及的对象加锁
    4.DML锁(数据锁):当用户使用DML语句更新数据时,ORALCE会自动对涉及的对象加DML锁
        从封锁粒度角度来看,DML锁可以分为行级锁和表级锁两个层次
        A.行级锁(事务锁,TX锁)
        产生的原因:一个事务第一次执行更改(INSERT,UPDATE,DELETE,SELECT...FOR UPDATE)时,会获取一个TX锁操作。
        行级锁不只针对一行记录,事务中涉及的被更新的行都拥有行级锁,ORACLE数据库行上没有共享锁(S锁),行级别的锁被用于在操作表中数据期间(在未提交或回退事务),防止其他用户对正在操作的行的数据进行修改操作。即行级别的锁按行来保护数据,防止并发访问相同的行。
        注意:要想获得某个表上的TX锁,事务必须先获得该表上的TM锁。

        B.表级锁(TM锁):
            当要在表上加锁时,要检查申请该锁与原有的表级锁是否兼容,还要检查它与表中每一行上的锁是否兼容,当然也可以用LOCK TABLE语句手动设置一个表级别的锁。目的是防止对表结构进行修改操作。
            意向锁(intent lock)表示ORACLE需要在行上获取共享锁或排他锁
                包括:意向共享锁(IS),意向排他锁(IX),共享意向排他锁(SIX)等类型
                意向共享锁(IS):表示事务要在表中的行上应用共享锁(S)
1、 IS锁(Intended Share Lock即意向共享锁)

指:如果对一个节点加IS锁,则表示对它的所有下级节点有加S锁的意向;如果对一个节点加S锁,则必须先对该节点的各个上级节点加IS锁。

2、 IX锁(Intended eXclusive Lock即意向排他锁)

指:如果对一个节点加IX锁,则表示对它的所有下级节点有加X锁的意向;如果对一个节点加X锁,则必须先对该节点的各个上级节点加IX锁。

3、 SIX锁(Share Intented eXclusive Lock即共享意向排他锁)

指:如果对一个节点加SIX锁,则表示对它加S锁,然后再加IX锁,即SIX=S+IX。


    当一个事务要修改一个对象时,加X锁
    当一个事务要读到一个对象时,加S锁
    
    当在一个数据库资源上放置了一种类型的锁时,其他事务只有请求与该锁兼容的锁,才会被批准,否则必须等待当前锁释放或锁超时后才能访问指定的数据库源
    
    
    粒度越小,数据库的并发性就越高,管理锁的开销就越大
        
    锁的特点

           ORACLE是通过队列机制来管理锁的。ORACLE中的锁是不受限制也不会自动升级的,这是和MSSQL中的不同之处。ORACLE中的查询语句是不会锁定数据的,前提是不带FOR UPDATE 子句的SELECT语句。因为ORACLE的查询是通过使用在撤销空间中所存储的数据被锁定之前的前映像来成功地执行的。这种方式提高了并发度,并保证了事务不会读取到脏数据。


事务的隔离级别:
    

    隔离级别程序越低,数据库的并发性越好,隔离级别程序越高,数据库的并发性越差
    READ COMMITTED    最低
    SERIALIZABLE    最高
    READ-ONLY    中等
1、 一级锁定协议是指事务T在修改对象之前,必须先对该对象进行加X锁,并直到事务结束时才释放该X锁,如果事务T仅仅是读取对象就,则不需进行任何加锁。一级锁定协议避免了数据修改丢失,但是无法避免脏读、不可重复读。

2、 二级锁定协议是指在一级协议的基础上,加上事务T在读取对象之前必须加S锁,读完后立即释放S锁。二级锁定协议避免了数据修改丢失、脏读。但是避免不了不可重复读。

3、 三级锁定协议是指在一级锁定协议的基础上,加上事务T在读取对象之间必须加S锁,直到事务结束后才释放S锁。三级锁定协议避免了数据修改丢失、脏读、不可重复读。


           锁的初始化参数:

           1、DDL_WAIT_FOR_LOCKS:该参数是动态参数,用于控制DDL语句是否需要等待锁。默认是FALSE,表示不会等待锁(即NOWAIT方式)。当为TRUE时,表示会等待锁。使用

ALTER SESSION 或 ALTER SYSTEM语句更改该参数的值。

           2、DDL_LOCKS:该参数是静态参数。用于指定DML锁的最大个数,取值范围是20到无限值。该参数默认值为TRANSACTIONS初始化参数的4倍,表示1个事务平均需要4个锁。使用

    ALTERSYSTEM …SCOPE=SPFILE语句更改该参数的值,而且必须重新启动数据库。

4、 ENQUEUE_RESOURCES:该参数是静态参数。用于指定锁管理器可以并发锁定的资源数。使用 ALTER SYSTEM …SCOPE=SPFILE更改该参数,需要重启数据库。

5、 DISTRIBUTED_LOCK_TIMEOUT:该参数是静态参数。用于指定分布式事务等待锁定资源的总计时间,其单位是秒。默认为60秒。使用

ALTER SYSTEM …SCOPE=SPFILE更改该参数同样需要重启数据库。
    
解决锁争用的策略及方法:

1、 不应该运行上事务,在操作时应该及时地使用COMMIT和ROLLBACK语句。

2、 避免使用表锁,而是使用ORACLE默认的加锁机制。

3、 在更改数据之前,可以使用 SELECT … FOR UPDATE NOWAIT语句试探性的加锁,通过返回的提示了解具体情况,避免莫名的等待。

4、 非高峰时期使用DDL语句。
及时检测系统中是否存在锁,调查锁存在的原因,适当时机使用 ALTER SYSTEM KILL SESSION‘sid,serial#’杀死锁。



设置自动提交:
    SET AUTO[COMMIT] {ON|OFF|IMM[EDIATE]|N}
    SET AUTOCOMMIT ON
    SHOW AUTOCOMMIT;    //查看
    SYS AS SYSDBA@ORCL>SHOW AUTOCOMMIT;
    autocommit OFF
    
在执行的语句中提交事务:
    COMMIT [WORK]
    
    DECLARE
    BEGIN
    COMMIT WORK;
    END;


回滚事务:
    ROLLBACK    //将会清除从事务起点或某个保存点开始所有对数据的修改操作
    两个DML语句中间有个隐式的COMMIT提交的动作
    CREATE
    COMMIT
    CREATE

定义保存点:
    使用ROLLBACK可以将数据回滚到保存点的位置
    SAVEPOINT <保存点名>
    DML语句
    ROLLBACK TO <保存点名>    //返回定义SAVEPOINT时的状态
    
查看事务信息:
    SYS AS SYSDBA@ORCL>SELECT ADDR,STATUS,START_TIME,NAME FROM V$TRANSACTION;

    ADDR     STATUS       START_TIME           NAME
    -------- ---------------- -------------------- --------------------
    37AE6A78 ACTIVE       12/26/14 16:10:08    

命名事务:
    使用SET TRANSACTION NAME命名事务
    
    SYS AS SYSDBA@ORCL>DECLARE
  2  IDCARD VARCHAR2(50):=‘1000‘;
  3  BEGIN
  4  SET TRANSACTION NAME ‘INSERTTRANSACTION‘;
  5  INSERT INTO HR.TEST3 VALUES(IDCARD);
  6  END;
  7  /

PL/SQL procedure successfully completed.    
    
    
SYS AS SYSDBA@ORCL>SELECT ADDR,STATUS,START_TIME,NAME FROM V$TRANSACTION WHERE NAME=‘INSERTTRANSACTION‘;

ADDR     STATUS       START_TIME           NAME
-------- ---------------- -------------------- --------------------
37AE6A78 ACTIVE       12/26/14 16:15:03    INSERTTRANSACTION

1 row selected.



嵌套事务和自治事务
    
    嵌套事务的内层事务需要定义为自治事务,所谓自治事务即指可以独立对本事务进行提交,但并不影响外层事务
    外层事务中执行回滚操作也不会影响内层的自治事务
    
    声明自治事务:
    PRAGMA AUTONOMOUS_TRANSACTION;
    
    V$LOCKED_OBJECT:视图查看当前存在的死锁信息:
    SELECT * FROM V$LOCKED_OBJECT;

    查看死锁信息:(只显示产生死锁的SQL语句)
    SYS AS SYSDBA@ORCL>SELECT T2.USERNAME,T2.SID,T2.SERIAL#,T2.LOGON_TIME,T3.SQL_TEXT
      2  FROM V$LOCKED_OBJECT T1,V$SESSION T2, V$SQLTEXT T3
     3  WHERE T1.SESSION_ID=T2.SID AND T2.SQL_ADDRESS=T3.ADDRESS
      4  ORDER BY T2.LOGON_TIME;
    
    查看被阻塞的会话信息
    DBA_WAITERS
    SELECT * FROM DBA_WAITERS;
    
    查看死锁中占用资源的会话信息
    DBA_BLOCKERS:视图可以查看死锁中占用资源的会话信息,这些会话并不等待被锁定的资源,但却持有另外一个会话等待的数据库对象上的锁,HOLDING_SESSION:表示持有锁的会话ID

    通过结束会话的方式解除死锁:
    ALTER SYSTEM KILL SESSION ‘SID,SERIAL#‘;
    
    设置READ COMMITTED事务隔离级别选项
    SET TRANSACTION ISOLATION LEVEL
    
    SET TRANSACTION ISOLATION LEVEL
    {
        READ COMMITTED | SERIALIZABLE
    }
    
    READ COMMITTED事务隔离级别可以避免脏读
    
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
    

    设置SERIALIZABLE事务隔离级别
    SERIALIZABLE事务隔离级别是限制最大的级别,它可以在事务查询的数据集上放置一个范围锁,在事务提交或回滚之前,禁止其他连接在范围锁内修改或插入数据
    作用:可以避免插入数据产生的幻想数据
    一个事务中多次读到同一表中的内容可以获取到完全相同的数据,无论在这个过程中的数据是否发生变化
    


    设置READ ONLY事务隔离级别
        
    READ ONLY是SERIALIZABLE事务隔离级别的子集,这个级别中仅仅能看见在本事务开始前由其它事务提交的更改,而且不能执行DML语    句
    SET TRANSACTION READ ONLY;
    
    
    
    

    
    
    
    
    

        
    
        
    
    

    
   

事务与锁定

原文:http://rscpass.blog.51cto.com/771159/1612753

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!