zoukankan      html  css  js  c++  java
  • 数据库加锁

    1.加锁的情况

    数据库使用独占式封锁机制。在执行增删改语句时,会先进行锁表,直到commit或回滚。

    如:A程序对表table1insert,还未commit时,B程序对表table1进行insert,此时会发生资源异常的情况,即锁表

    锁表常发生于并发而不是并行。(并发在微观上并不是同时执行)

    2.锁机制:

     

    表级锁:

      优点

    • 实现逻辑简单,开销小。

    • 获取锁和释放锁的速度快。

    • 由于表级锁一次会将整个表锁定,所以能很好的避免死锁问题。

      缺点

    • 由于锁粒度最大,因此出现争用被锁定资源的概率也会最高,致使并发度十分低下

    行级锁:

    .  优点

    • 由于锁粒度小,争用率低,并发高。

     .  缺点

    • 实现复杂,开销大。

    • 加锁慢、容易出现死锁

    页级锁:

    开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

    2.锁的种类

    共享锁(行锁):多个事务对于同一数据可以共享一把锁。都能访问到数据,但不能修改。

    排他锁(行锁):允许获取排他锁的事务更新数据,阻止其他事务取得相同的数据集共享读锁和排他写锁。

    意向共享锁(表级锁):事务打算给数据行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。

    意向排他锁(表级锁):事务打算给数据行加排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

    当前锁模式/是否兼容/请求锁模式

    X

    IX

    S

    IS

    X

    冲突

    冲突

    冲突

    冲突

    IX

    冲突

    兼容

    冲突

    兼容

    S

    冲突

    冲突

    兼容

    兼容

    IS

    冲突

    兼容

    兼容

    兼容

     意向锁是InnoDB自动加的,不需用户干预。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及的数据集加排他锁(X);对于普通SELECT语句,InnoDB会自动给涉及数据集加共享锁(S);事务可以通过以下语句显式给记录集加共享锁或排锁。

    共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE

    排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE

        用SELECT .. IN SHARE MODE获得共享锁,主要用在需要数据依存关系时确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT ... FOR UPDATE方式获取排他锁。 

    3.分类依据:

    按操作划分,可分为DML锁DDL锁

    按锁的粒度划分,可分为表级锁行级锁页级锁(mysql)

    按锁级别划分,可分为共享锁排他锁

    按加锁方式划分,可分为自动锁显示锁

    按使用方式划分,可分为乐观锁悲观锁

    DML锁(data locks,数据锁),用于保护数据的完整性,其中包括行级锁(Row Locks (TX锁))、表级锁(table lock(TM锁))。 DDL锁(dictionary locks,数据字典锁),用于保护数据库对象的结构,如表、索引等的结构定义。其中包排他DDL锁(Exclusive DDL lock)、共享DDL锁(Share DDL lock)、可中断解析锁(Breakable parse locks)

    4.减少锁表的概率:

       对于InnoDB表,主要有以下几点

        (1)InnoDB的行销是基于索引实现的,如果不通过索引访问数据,InnoDB会使用表锁。

        (2)InnoDB间隙锁机制,以及InnoDB使用间隙锁的原因。

        (3)在不同的隔离级别下,InnoDB的锁机制和一致性读策略不同。

        (4)MySQL的恢复和复制对InnoDB锁机制和一致性读策略也有较大影响。

        (5)锁冲突甚至死锁很难完全避免。

        在了解InnoDB的锁特性后,用户可以通过设计和SQL调整等措施减少锁冲突和死锁,包括:

    • 尽量使用较低的隔离级别

    • 精心设计索引,并尽量使用索引访问数据,使加锁更精确,从而减少锁冲突的机会。

    • 选择合理的事务大小,小事务发生锁冲突的几率也更小。

    • 给记录集显示加锁时,最好一次性请求足够级别的锁。比如要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁。

    • 减少insert 、update 、delete 语句执行 到 commite 之间的时间。如:批量执行改为单个执行、优化sql自身的非执行速度

    • 如果异常则对事务进行回滚

    • 不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。这样可以大减少死锁的机会。

    • 尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响。

    • 不要申请超过实际需要的锁级别;除非必须,查询时不要显示加锁。

    • 对于一些特定的事务,可以使用表锁来提高处理速度或减少死锁的可能。

    5.查看锁的征用次数:

    行级锁:

    mysql> show status like 'InnoDB_row_lock%';

    mysql> show status like 'InnoDB_row_lock%';
    +-------------------------------+-------+
    | Variable_name                 | Value |
    +-------------------------------+-------+
    | InnoDB_row_lock_current_waits | 0     |
    | InnoDB_row_lock_time          | 0     |
    | InnoDB_row_lock_time_avg      | 0     |
    | InnoDB_row_lock_time_max      | 0     |
    | InnoDB_row_lock_waits         | 0     |
    +-------------------------------+-------+

    表级锁:

    show status like ‘table%’;

     

    一、按操作划分,可分为DML锁DDL锁

    二、按锁的粒度划分,可分为表级锁行级锁页级锁(mysql)

    三、按锁级别划分,可分为共享锁排他锁

    四、按加锁方式划分,可分为自动锁显示锁

    五、按使用方式划分,可分为乐观锁悲观锁

    DML锁(data locks,数据锁),用于保护数据的完整性,其中包括行级锁(Row Locks (TX锁))、表级锁(table lock(TM锁))。 DDL锁(dictionary locks,数据字典锁),用于保护数据库对象的结构,如表、索引等的结构定义。其中包排他DDL锁(Exclusive DDL lock)、共享DDL锁(Share DDL lock)、可中断解析锁(Breakable parse locks)

  • 相关阅读:
    Mybatis入门
    Ajax
    产品经理之产品规划
    产品经理之用户研究(下)
    产品经理之用户研究(上)
    Spring Cloud
    Spring MVC
    synchronized
    Spring Boot入门
    Spring
  • 原文地址:https://www.cnblogs.com/lyqf/p/14364439.html
Copyright © 2011-2022 走看看