InnoDB-----第六章 锁

第6章 锁


​ 锁的出现主要是最大程度利用数据库的并发访问的同时,还要确保每个用户能以一致的方式读取和修改数据

1. 什么是锁

​ 锁机制用于管理对共享资源的并发访问.InnoDB存储引擎会在行级别上对表数据上锁.数据库系统使用锁是为了支持对共享资源并发访问,提供数据的完整性和一致性.

​ MyISAM存储引擎使用表锁,读取性能良好,但是并发插入性能就要差一些.

2. lock与latch

​ 锁分为两种:lock与latch.在数据库中,lock与latch都可以被称为锁,但是latch一本被称为闩(shuan)锁(轻量级).要求锁定的时间非常短,如果持续时间成,应用的性能会非常差.

​ 在InnoDB存储引擎中,latch又可以被分为mutex(互斥量)和rwlock(读写锁).设计的目的是用来摆正并发线程操作临界资源的正确性,通常没有死锁检测.

​ lock的对象是事务,用来锁定的是数据库中的对象(表,页,行等).一般lock的对象只在事务提交或者回滚后释放,有死锁机制.

lock与latch的比较:

locklatch
对象事务线程
保护数据库内容内存数据结构
持续时间整个事务过程临界资源
模式行锁,表锁,意向锁读写锁,互斥量
死锁有死锁检测和处理仅通过应用程序的顺序保证无死锁现象
存在于lock manager的哈希表每个数据结构的对象中

3. InnoDB存储引擎中的锁

(1). 锁的类型

​ InnoDB存储引擎实现了以下两种锁:

  • 共享锁(S Lock,读锁),允许读取一行数据
  • 排他锁(X Lock,写锁),允许事务删除或者更新一行数据

​ 以上两种都是行锁

​ 读锁和读锁之间是兼容的,写锁与任何锁都不兼容.

​ InnoDB存储引擎支持意向锁,即表级别的锁:

意向锁是为了解决行锁和表锁共存时产生冲突的问题而产生的.

当一个事务A得到了表中一行的行锁时,另一个事务B获取到整个表的表锁,那么两个锁就会冲突.

那么,在给一行加行锁时,先给整个表加上意向锁,那么在加表锁时会先判断意向锁(因为意向锁是表锁),然后再进行加锁.

这里的锁都指的是写锁.

意向锁

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

(2). 一致性非锁定读

不加锁读,也就是读之前某一时刻的快照

​ 一致性的非锁定读是指InnoDB存储引擎通过行多版本空值的方式开读取当前执行时间数据库中行的数据.(多版本读取快照)

​ 快照数据是指该行的之前版本的数据,是通过undo段(用于回滚的老版本数据链中的一个节点)来完成的,因此没有任何空间开销.

​ 一致性非锁定读是InnoDB存储引擎默认的读取方式,但是不同的事务隔离情况下,读取的方式可能会发生改变(或者快照数据的定义不同).

​ 读未提交和可重复读下,使用一致性非锁定读,但是读未提交中总是读取最新的一份快照数据,而可重复读下,读取事务开始是的行数据版本.

​ 在默认情况下,可以读到的其他事物提交前的数据,这里是指undo页中的回滚数据,而不是说数据库中的数据未发生改变.

(3). 一致性锁定读

当前读,也就是加读锁

  • select…for update : 加写锁
  • select…lock in share mode : 加读锁

(4). 自增长与锁

每一个自增长的插入:
开启事务 --> 获取自增长值 --> 重新设置自增长值 --> 插入相应数据 --> 提交事务
			    |________________________________|
								|
							  锁有效

​ 自增长是通过自增长计数器实现的,每当对含有自增长计数器的表进行插入操作时,计数器就会被初始化,并通过查询当前表自增长列的最大值来重新设置值.这个查询的过程中,需要对表进行加锁.而这个锁在select语句执行完之后就会释放,而不是等到事务结束.

​ 这样的模式在大插入量的情况下效率底下,在MySQL 5.1.22版本之后,InnoDB存储引擎提供一种轻量级互斥量(原子性变量)的自增长实现机制.

​ 在InnoDB存储引擎中,自增长的值必须是索引列,且必须是索引的第一个列.

(5). 外键和锁

​ 对于外键,InnoDB存储引擎会自动的加上一个索引,以避免表锁.

​ 对于连接查询,会给父表加读锁.

4. 锁的算法

(1). 行锁的三种算法

  • Record Lock:单行锁
  • Gap Lock:间隙锁(行与行之间的间隙,用于防止插入数据引起的幻读)
  • Next-Key Lock:区间锁,上面两种锁的结合(InnoDB存储引擎对于行的查询都使用这种锁)

​ 当查询的索引含有唯一属性时,InnoDB存储引擎会对Next-Key Lock进行优化,降为Record Lock

​ 对于辅助索引的加锁,会在Next-Key Lock的基础上在给后继的一个间隙加锁

5. 锁问题

(1). 脏读

​ 事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

​ 脏数据就是指内存中和磁盘中不一致的数据.

​ 使用事务开启前的快照读(读取修改数据的事务开启前的快照数据)可以避免脏读.

(2). 不可重复读

​ 事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。

​ MVCC可以解决不可重复读,读取当前事务开始时对应的版本数据,

(3). 幻读

​ 同样的条件,第1次和第2次读出来的**记录数**不一样。

​ 事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。

​ InnoDB使用间隙锁解决幻读的问题.

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

6. 阻塞

​ 一个事物中对某些数据已经加锁,另一个事务也需要对事务上锁,那么就需要等待前一个事务将锁释放,在此期间会阻塞进程.

​ 事务如果阻塞超时,会抛出异常,但不会提交事务也不会回滚,是非常危险的状态.

7. 死锁

(1). 死锁的概念

​ 死锁是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种相互等待的现象.

​ 回滚:一旦死锁,两个事务都回滚

​ 超时:设置超时时间,超出这个时间的事务回滚

​ 等待图:等待图保存锁信息链表和事务等待链表.每个事务请求锁并发生等待时都会判断是否存在回路,如果存在那么发生了死锁,会选择回滚undo量最小的事务.

(2). 死锁概论

​ 死锁发生的概论应该是非常低的.

8. 锁升级

​ 锁升级是指将当前锁的粒度降低,例如将1000个行锁升级为一个页锁,或者将业所升级为表锁.

​ SQL server认为锁是一种稀缺资源,所以会在适当的时候进行锁升级.

​ InnoDB存储引擎不存在锁的升级问题,InnoDB中根据每个页对锁进行管理,大大减小了锁占有的空间,而且对于一个页中的数据来说,对一行加锁和对多行加锁所造成的开销是一样的.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值