zoukankan      html  css  js  c++  java
  • 数据库锁:各种锁

    一、悲观锁和乐观锁

      我们经常在开发中遇到数据库并发处理时,处理不一致的问题。需要对程序做并发控制。
    典型的并发时出现的冲突有两种:
    1、丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。
    例如X=0  A1把X=X+1  A2也设置X=X+1    如果A1和A2同时执行,可能出现最终X=1的情况。而我们需要得到的是X=2  。   这就需要update处理为串行化的。
    2、脏读:读到的数据可能是旧的。    初使X=0    A1把X设置为1,A2读取时X是1,但A1后面又修改成了2,或回滚到了0,那么A2读取的数据就是脏数据。
    A2读取的是未提交的数据。一般数据库不会设为读未提交,所以一般不会出现脏读。

    那什么是乐观锁,什么是悲观锁。

    悲观锁:需要使用数据库的锁机制,如数据库有表级排它锁,有行级排它锁。
    假定一切操作都可能发现并发冲突,所以采取悲观态度。通过加锁,屏蔽一切可能违反数据完整性的操作
    比方select * from table for update;  就是表锁,
    select * from table where x = 1 for update; 就是行锁。
    当使用for update后,其它会话还是可以执行select操作,但无法执行select xx for update操作,只有当前会话commit后,其它for update操作才会被执行。
    典型例子可以参考quartz集群的锁机制:http://blog.itpub.net/11627468/viewspace-1764753/
    当然,此时也不可以update,update需要等select xx for update 所在会话commit后才能执行。
    注:mysql需要设置autocommit=0

    乐观锁:其实不是真实的去锁住记录不让访问,或者不让更新。
    假定操作很少发生冲突,一般对于读多写少的情况。只在提交操作时检查是否违反数据完整性。[1] 乐观锁不能解决脏读的问题。
    可以通过版本号是否比上个版本号或者时间戳来实现。
    对于冲突检测后的处理,需要业务逻辑去处理。

    二、排它锁和共享锁
    在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。
    当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。
    数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。


    三、表级锁和行级锁

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

    值  锁模式  锁描述  SQL
    0 NONE 1  NULL  空  SELECT
    2  SS(ROW-S)  行级共享锁
    其他对象只能查询这些数据行  SELECT FOR UPDATE、LOCK FOR UPDATE、
    LOCK ROW SHARE
    3  SX(ROW-X)  行级排它锁
    在提交前不允许做DML操作  INSERT、UPDATE、DELETE、
    LOCK ROW SHARE
    4  S(SHARE)  共享锁  CREATE INDEX、LOCK SHARE
    5  SSX(S/ROW-X)  共享行级排它锁  LOCK SHARE ROW EXCLUSIVE
    6  X(eXclusive)  排它锁  ALTER TABLE、DROP TABLE、DROP INDEX、
    TRUNCATE TABLE、LOCK EXCLUSIVE

    四、几个问题
    1.UPDATE/DELETE操作会将RS锁定,直至操作被COMMIT或者ROLLBACK;
    若操作未COMMIT之前其他session对同样的RS做变更操作,则操作会被hold,直至前session的UPDATE/DELETE操作被COMMIT;


    2.session内外SELECT的RS范围
    前提:INSERT、UPDATE操作未COMMIT之前进行SELECT;
    若在同一session内,SELECT出来的RS会包括之前INSERT、UPDATE影响的记录;
    若不在同一session内,SELECT出来的RS不会包括未被COMMIT的记录;


    3.SELECT.... FOR UPDATE [OF cols] [NOWAIT/WAIT] [SKIP LOCKED]
    OF cols:只锁定指定字段所在表的RS,而没有指定的表则不会锁定,只会在多表联合查询时出现;
    NOWAIT:语句不会hold,而是直接返回错误ORA-00054: resource busy and acquire with NOWAIT specified;
    WAIT N:语句被hold N秒,之后返回错误ORA-30006: resource busy; acquire with WAIT timeout expired;
    SKIP LOCKED:不提示错误,而是直接返回no rows selected;
    以上几个选项可以联合使用的,比较推荐的有:
    SELECT.... FOR UPDATE NOWAIT:对同一RS执行该SQL时,直接返回错误;
    SELECT.... FOR UPDATE NOWAIT SKIP LOCKED:对同一RS执行该SQL时,直接返回空行;
    PS:当RS被LOCK住之后,只对同样请求LOCK的语句有效,对无需LOCK的SELECT语句并没有任何影响;





    以上悲观锁和乐内容参考:
    http://www.cnblogs.com/guyufei/archive/2011/01/10/1931632.html
    spring锁实现参数:
    http://blog.itpub.net/12158104/viewspace-374745
    关于隔离级别可以参考:
    http://blog.itpub.net/11627468/viewspace-1793036/
    关于数据库的锁可以参考:
    http://zhidao.baidu.com/link?url=zRnaslJ8INtEviT--BzrT2bMOqf4LJQzL-NQg2ECu6l-s-xPHi11bBlNjN2_zyNrwd9M0ZnbelQntmfYPB0ifq

  • 相关阅读:
    简单对拍
    搜索感想
    L1434滑雪
    记忆化搜索
    L3956棋盘
    USACO 数字三角形
    枚举顺序
    蓝桥计算
    用户态和内核态IO过程
    Mybatis的结果集中的Do要不要有setter
  • 原文地址:https://www.cnblogs.com/hllnj2008/p/5333108.html
Copyright © 2011-2022 走看看