InnoDB 锁

1.不同引擎支持不同锁机制,InnoDB支持 行锁。

2.表锁,行锁区别:

  1. 表锁开销小,加锁块,不会出现死锁;锁粒度大,发生锁冲突概率大,并发性能小。
  2. 行锁开销大,加锁慢,会出现死锁;锁粒度小,发生锁冲突概率小,并发度也相对高。

3.读锁

  • S锁: 共享锁,允许其他事务读,但是不允许进行增删改操作。

4.写锁

  • X锁:排它锁,不允许其他任何操作,包括读,写锁优先级最高。

5.MDL锁:

  • 开启查询事务之后,不再执行任何DDL操作。

6.意向锁:

  • 在InnoDB引擎中意向锁是 表级锁,而且有2种意向所类型,分别是:
  1. 意向排它锁(IX):指在给数据行加排它锁(写锁)时必须获得该表的IX锁。
  2. 意向共享锁(IS):指给数据行加共享锁(读锁)时必须获得该表的IS锁。

7.行锁种类:

  1. 单个行记录锁record lock : 就是普通对指定一行加锁,InnoDB的行锁是加在 索引 上面的。
  2. 间隙锁GAP lock : RR事务隔离级别管用,顾名思义它是对记录中间的间隙加锁,保持你记录前后关系,可以用来锁定记录的某个范围,该范围内不允许插入其他数据。包含下范围,不包含上范围。
  3. 记录锁和间隙锁的组合叫做 next-key lock : 扫描索引记录时,先对选中的索引加上记录锁,再对索引记录两边间隙加上间隙锁。
  • 普通索引默认是 next-key lock
  • next-key lock 可以避免幻读。

8.lock 和 latch

  1. latch 轻量级锁,锁的对象是线程。又分为mutex(互斥量)和 rwlock(读写锁)。其目的是用来保证并发线程临界操作资源的正确性,并且通常没有死锁检测机制。
  2. lock 锁的是事务,用来锁定数据库中的对象,如 表,页,行,并且一般在commit或者ROLLBACK之后释放。

9.读取行为

  1. 一致性非锁定读: InnoDB默认读取方式。
    • 指读取某一行数据时如果该行数据正在进行DELETE或者UPDATE操作,此时不会去等待该锁释放,而是去读一个快照数据。
    • 此快照数据来自 undo 段,而undo本来是用于回滚事务,因此读取快照数据没有额外的开销。
    • 读取快照是不需要上锁的因为没有事务会对历史数据进行修改。
  2. 一致性锁定读: 某些情况下读取操作需要保持数据一致性。
    • 第一种可以在进行读取操作时可以手动加X锁:SELECT ... FOR UPDATE, 其他事务不能对已锁定行上加任何锁。
    • 第二种可以在读取操作时加一个S锁: SELECT ... LOCK IN SHARE MODE ,其事务可以对已锁定的行加S锁,当是加X锁线程就会被阻塞。
    • 注意:这2种情况必须在事务中,事务提交了锁也就释放了。

10.死锁

  1. 解决死锁最简单的方式就是消除等待,把所有等待都变成回滚,再重写开始事务。
  2. 设定超时,2个等待的事务某个事务等待时间到了阀值就进行回滚,另一个事务就开始执行。
  3. 采用 wait-for graph 方式来主动检测死锁,他要求数据库保存2种信息用来检测
    1. 锁的信息链表
    2. 事务等待链表
    • 他可以根据以上两种信息构造一张图,如果图中有回路则代表有死锁,如果发现死锁会回滚undo量最小的事务。

11.锁升级

  • 比如1000个行锁升级为一个页锁,使锁的粒度升高。
  • Microsoft SQL Server 的锁是一种稀缺资源所以会频繁进行锁升级,InnoDB的锁并不是稀缺资源。
  • InnoDB不支持锁升级,innodb行锁采用位图存储,理论上一个记录只需要一个bit位。锁的基本单位是行,但锁是通过事务和页来进行管理和组织,创建锁的实例是lock_t,一个lock_t实例对应于一个索引页面的所有记录。所以锁一行和锁一页开销一样大。
原文地址:https://www.cnblogs.com/mibloom/p/9633561.html