mysql锁机制

515 阅读4分钟

锁:

  • latch一般称为闩锁(轻量级的锁),因为其要求锁定的时间必须非常短。
  • lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。
latch :
  • 在InnoDB存储引擎中,latch又可以分为mutex(互斥量)和rwlock(读写锁)。
  • 其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制。
lock:
* InnoDB存储引擎支持多粒度(granular)锁定,这种锁定允许事务在行级上的锁和表级上的锁同时存在
行级锁
InnoDB存储引擎实现了如下两种标准的行级锁:
* 共享锁(S Lock),允许事务读一行数据。
* 排他锁(X Lock),允许事务删除或更新一行数据。
意向锁
  • 为了支持在不同粒度上进行加锁操作,InnoDB存储引擎支持一种额外的锁方式,称之为意向锁(Intention Lock)

  • 意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度(fine granularity)上进行加锁。数据库,表,页,行。

  • 对最细粒度的对象进行上锁,那么首先需要对粗粒度的对象上锁。
    例子: 对页上的记录r进行上X锁,那么分别需要对数据库A、表、页上意向锁IX,最后对记录r上X锁。若其中任何一个部分导致等待,那么该操作需要等待粗粒度锁的完成。

  • InnoDB存储引擎支持意向锁设计比较简练,其意向锁即为表级别的锁。设计目的主要是为了在一个事务中揭示下一行将被请求的锁类型。
    1)意向共享锁(IS Lock)事务想要获得一张表中某几行的共享锁
    2)意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁

  • 由于InnoDB存储引擎支持的是行级别的锁,因此意向锁其实不会阻塞除全表扫以外的任何请求。

锁竞争查看
  • 从InnoDB1.0开始,在INFORMATION_SCHEMA架构下添加了表INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS。通过这三张表,用户可以更简单地监控当前事务并分析可能存在的锁问题。
INNODB_TRX表:
  • 该表只是显示了当前运行的InnoDB事务,并不能直接判断锁的一些情况。如果需要
INNODB_LOCKS表:
  • 查看锁,则还需要访问表INNODB_LOCKS
INNODB_LOCK_WAITS表:
  • 表INNODB_LOCK_WAITS,可以很直观地反映当前事务的等待情况。
一致性的非锁定读(consistent nonlocking read)
  • 是指InnoDB存储引擎通过行多版本控制(multi versioning)的方式来读取当前执行时间数据库中行的数据。如果读取的行正在执行DELETE或UPDATE操作,这时读取操作不会因此去等待行上锁的释放。相反地,InnoDB存储引擎会去读取行的一个快照数据。

  • 在事务隔离级别READ COMMITTED和REPEATABLE READ(InnoDB存储引擎的默认事务隔离级别)下,InnoDB存储引擎使用非锁定的一致性读。然而,对于快照数据的定义却不相同。

    在READ COMMITTED事务隔离级别下,对于快照数据,非一致性读总是读取被锁定行的最新一份快照数据。

    在REPEATABLE READ事务隔离级别下,对于快照数据,非一致性读总是读取事务开始时的行数据版本。

  • InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作:

  • SELECT…FOR UPDATE

    • SELECT…FOR UPDATE对读取的行记录加一个X锁,其他事务不能对已锁定的行加上任何锁。
  • SELECT…LOCK IN SHARE MODE。

    • SELECT…LOCK IN SHARE MODE对读取的行记录加一个S锁,其他事务可以向被锁定的行加S锁,但是如果加X锁,则会被阻塞。
  • 对于一致性非锁定读,即使读取的行已被执行了SELECT…FOR UPDATE,也是可以进行读取的,这和之前讨论的情况一样。
    SELECT…FOR UPDATE,SELECT…LOCK IN SHARE MODE必须在一个事务中,当事务提交了,锁也就释放了。

自增锁:
  • 在InnoDB存储引擎的内存结构中,对每个含有自增长值的表都有一个自增长计数器(auto-increment counter)。
  • 当对含有自增长的计数器的表进行插入操作时,这个计数器会被初始化,执行如下的语句来得到计数器的值:
    SELECT MAX(auto_inc_col) FROM t FOR UPDATE;插入操作会依据这个自增长的计数器值加1赋予自增长列。这个实现方式称做AUTO-INC Locking。
锁的算法
  • record lock (单个行记录锁)
  • gap (间隙锁)
  • next-key lock = gap lock + record lock (锁定范围+记录本身)