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)

  • 相关阅读:
    53. Maximum Subarray
    64. Minimum Path Sum
    28. Implement strStr()
    26. Remove Duplicates from Sorted Array
    21. Merge Two Sorted Lists
    14. Longest Common Prefix
    7. Reverse Integer
    412. Fizz Buzz
    linux_修改域名(centos)
    linux_redis常用数据类型操作
  • 原文地址:https://www.cnblogs.com/lyqf/p/14364439.html
Copyright © 2011-2022 走看看