MySQL锁概述

  锁(locking)的机制是区分数据库系统文件系统的一个关键特征。

  锁机制用于管理对共享资源的并发访问。InnoDB存储引擎会在行级别上对表数据上锁,这固然不错。不过InnoDB存储引擎也会在数据库内部其他多个地方使用锁,从而允许对多种不同资源提供并发访问。例如:操作缓冲池中的LRU(Least Recently Used的缩写,即最近最少使用)列表,删除,添加,移动LRU列表中的元素,为了保证一致性,必须有锁的介入。数据库系统使用锁是为了对共享资源进行并发访问。保证数据的完整性和一致性。

     一、各数据库不同或存储引擎不同,锁实现也不同

  对于MyISAM引擎,其锁是表锁设计,并发情况下读没有问题,但是并发插入时的性能就要差一些了。

  对于Microsoft SQL Server数据库,在Microsoft SQL Server2005版之前其都是页锁的,相对表锁的MyISAM引擎来说,并发性能有所提升。页锁容易实现,然而对于热点数据页的并发问题依然不能为例。

                 到了2005版本,Microsoft SQL Server开始支持乐观并发悲观并发,在乐观并发下开始支持行级锁,但是其实现方式与InnoDB存储引擎的实现方式完全不同。在Microsoft SQL Server下,锁是一种稀有的资源,锁越多开销就越大,因此它会有锁升级,这种情况下,行锁会升级到表锁,这时并发的性能又回到了从前。

  Oracle和InnoDB存储引擎锁的实现类似,提供一致性的非锁定读、行级锁支持。行锁没有额外相关开销,并可以同时得到并发性和一致性。

      二、lock 与 latch

  在数据库中,lock与latch都可以被成为“锁”,但是二者有着截然不同的含义。

  latch一般称为闩(shuan)锁(轻量级的锁),因为其要求锁定的时间必须非常短,若持续的时间长,则应用的性能会非常差。在InnoDB存储引擎中,latch又可以被分为mutex(互斥锁)和rwlock(读写锁)。其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制。

  lock的对象是事务,用来锁定的是数据库中的对象,如 表、页、行。并且一般lock的对象仅在事务commit或rollback后进行释放(不同事务隔离界别释放的时间可能不同)。此外,lock正如大多数数据库中一样,是有死锁机制的。

  (

当出现死锁以后,有两种策略:

  • 一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wait_timeout 来设置。
  • 另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑。

  )

                     lock 与latch的对比

  lock latch
对象  事务 线程
保护 数据库内容 内存数据结构
持续时间 整个事务过程 临界资源
模式 行锁、表锁、意向锁 读写锁,互斥锁
死锁 通过waits-for graph、time out等机制进行死锁检测与处理 无死锁检测与处理机制,仅通过应用程序加锁的顺序(lock leveling)保证无死锁的情况发生
存在于 lock Manager的哈希表中 每个数据结构的对象中

                  show engineinnodb mutex; 查看latch信息

      三、InnoDB引擎中的锁

    3.1 锁的类型

      InnoDB存储引擎实现了如下两种标准的行级锁:

      共享锁(S Lock),允许事务读一行数据。    select.....lock in share mode

      排他锁(X Lock),允许事务删除或更新一行数据  select .......for update

    锁兼容:如果一个事务T1已经获得了行r的共享锁,那么另外的事务T2可以立即执行获取行r的共享锁,因为读取并没有改变行r的数据。

    锁不兼容:但若有其他事务T3想获得r的排他锁,则其必须等待事务T1 T2释放行r上的共享锁。

                   排他锁和共享锁的兼容性

  X S
X 不兼容 不兼容
S 不兼容 兼容

    可以发现,X锁与任何的锁都不兼容,而S锁仅与S锁兼容。

    此外,InnoDB存储引擎支持多粒度(granular)锁定,这种锁定允许事务在行级上和表级上的锁同时存在。为了支持在不同粒度上进行加锁操作,InnoDB存储引擎支持一种额外的锁方式,称之为意向锁(Intention Lock)。意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度(fine granularity)上进行加锁。

  若将上锁的对象堪称一棵树,那么对最下层的对象上锁,也就是对最细粒度的对象进行上锁,那么首先需要对粗粒度的对象上锁。如下图:如果需要对页上的记录r上X锁,那么需要分别对数据库A、表、页上意向锁IX,最后对记录r上X锁。若其中任何一个部分导致等待,那么该操作需要等待粗粒度锁的完成。

     InnoDB存储引擎支持意向锁设计比较简练,其意向锁即为表级别的锁。设计目的的主要是为了在一个事务中揭示下一行将被请求的锁类型。

     1)意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁

     2)意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁

  IS IX S X
IS 兼容 兼容 兼容 不兼容
IX 兼容 兼容 不兼容 不兼容
S 兼容 不兼容 兼容 不兼容
X 不兼容 不兼容 不兼容 不兼容

     检查MySQL锁请求状态  show engine innodb status

    information_schema.INNODB_TAX 描述当前事务状态

    information_schema.INNODB_LOCKS 描述当前锁状态

    information_schema.INNODB_LOCK_WAITS 描述事务和锁的对应关系

        3.2 一致性非锁定读

        3.3 一致性锁定读

        3.4  自增长与锁

        3.5  外键和锁

      四、锁的算法

        4.1 行锁的三种算法

        4.2 解决 Phantom Problem (幻读问题)

      五、锁问题

        5.1 脏读

        5.2 不可重复度

        5.3 幻读

      六、阻塞

     七、死锁

     八、锁升级

原文地址:https://www.cnblogs.com/huan30/p/12295976.html