第六章 InnoDB存储引擎——锁

什么是锁
锁机制用于 管理对共享资源的并发访问
一、lock与latch
在数据库中,lock与latch都可以被称为锁,但是含义截然不同。
latch
latch一般称为闩( shuān)锁(轻量级的锁),其要求锁定的时间必须非常短。
闩锁分为:mutex(互斥量)、rwlock(读写锁)。其目的是用来保证并发现成操作临界资源的正确性,并且通常没有死锁检测机制。
lock
lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或rollback后进行释放(不同事务隔离级别释放的时间可能不同),有死锁检测机制。
二、InnoDB存储引擎中的锁
2.1 锁的类型
InnoDB存储引擎实现了如下两种标准的 行级锁: 
  • 共享锁(S Lock):允许事务读一行数据。 
  • 排他锁(X Lock):允许事务删除或更新一行数据。
锁兼容性:
什么是意向锁
意向锁是将锁定的对象分为多个层次(数据库级别、表级别、行级别),意向锁意味着事务希望在更细粒度上进行加锁
若对底层的记录r加X锁,则需要将对应树杈上的页、表、数据库A都增加IX锁。
InnoDB中的意向锁
InnoDB中的意向锁即为表级锁。分为:
  • 意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁 
  • 意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁
表级别的意向锁和行级锁兼容性
2.2 一致性非锁定读
什么是一致性非锁定读
指InnoDB存储引擎通过 行多版本控制(multi versioning)的方式来读取当前执行时间数据库中行的数据。如果读取的行正在执行DELETE或UPDATE操作,这时读取操作 不会因此去等待行上锁的释放。相反地,InnoDB存储引擎会去 读取行的一个快照数据。快找数据是该行之前版本的数据。
优点:极大的提升了数据库的并发性。
什么是多版本并发控制(MVCC)
一个行记录可能有不止一个快照数据,一般称这种技术为行多版本技术。由此带来的并发控制,称之为多版本并发控制(Multi Version Concurrency Control,MVCC)。
不同事务隔离级别的MVCC
在事务隔离级别READ COMMITTED和REPEATABLE READ下,InnoDB存储引擎使用非锁定的一致性读。然而,对于快照数据的定义却不相同。
  • READ COMMITTED:对于快照数据,非一致性读总是读取被锁定行的 最新一份快照数据
  • REPEATABLE READ:对于快照数据,非一致性读总是 读取事务开始时的行数据版本
2.3 一致性锁定读
什么是一致性锁定读
在某些情况下,用户需要显式地对数据库读取操作进行加锁以保证数据逻辑的一致性。这要求数据库支持加锁语句,即使是对于SELECT的只读操作。
InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作: 
  • SELECT…FOR UPDATE:读取的行记录加一个X锁,其他事务不能对已锁定的行加上任何锁
  • SELECT…LOCK IN SHARE MODE:对读取的行记录加一个S锁,其他事务可以向被锁定的行加S锁,但是如果加X锁,则会被阻塞。
SELECT…FOR UPDATE,SELECT…LOCK IN SHARE MODE必须在一个事务中,当事务提交了,锁也就释放了
2.4 自增长与锁
插入操作会依据这个自增长的计数器值加1赋予自增长列。这个实现方式称做AUTO-INC Locking。这种锁其实是采用一种特殊的表锁机制,为了提高插入的性能,锁不是在一个事务完成后才释放,而是在完成对自增长值插入的SQL语句后立即释放。
三、锁的算法
3.1 行锁的三种算法
InnoDB存储引擎有3种行锁的算法,分别是: 
  • Record Lock:单个行记录上的锁 
  • Gap Lock:间隙锁,锁定一个范围,但不包含记录本身 
  • Next-Key Lock∶Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身
InnoDB对于行的查询采用next-key lock。
当查询的索引含有唯一属性时,InnoDB存储引擎会对Next-Key Lock进行优化,将其降级为Record Lock。
Gap Lock的作用是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产生。
3.2 解决幻读问题
Phantom Problem是指:在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次的SQL语句可能会返回之前不存在的行。
InnoDB存储引擎默认的事务隔离级别是REPEATABLE READ,在该隔离级别下,其采用Next-Key Locking的方式来加锁。而在事务隔离级别READ COMMITTED下,其仅采用Record Lock
四、锁问题
4.1 脏读
脏数据是指事务对缓冲池中行记录的修改,并且还没有被提交的数据。
脏读:即读取脏数据,一个事物读取到了另一个事务未提交的数据。
4.2 不可重复读
在一个事务内两次读到的数据是不一样的情况,这种情况称为不可重复读。
不可重复读和脏读的区别是:脏读是读到未提交的数据,而不可重复读读到的却是已经提交的数据
五、死锁
死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象。
解决死锁问题最简单的一种方法是超时:即当两个事务互相等待时,当一个等待时间超过设置的某一阈值时,其中一个事务进行回滚,另一个等待的事务就能继续进行。 在InnoDB存储引擎中,参数innodb_lock_wait_timeout用来设置超时的时间。
除了超时机制,当前数据库还都普遍采用wait-for graph(等待图)的方式来进行死锁检测。
六、锁升级
锁升级(Lock Escalation)是指将当前锁的粒度降低。
在以下情况下依然可能发生锁升级: 
  • 由一句单独的SQL语句在一个对象上持有的锁的数量超过了阈值,默认这个阈值为5000。值得注意的是,如果是不同对象,则不会发生锁升级
  • 锁资源占用的内存超过了激活内存的40%时就会发生锁升级
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值