第六章:锁

锁机制是为了:最大程度利用数据库的并发访问,并确保每个用户以一致性读取和修改数据。

lock和latch

锁的类型

共享锁(s锁),允许事务读一行数据

排他锁(x锁),允许事务删除或者更新一行数据

 对同一行记录锁的兼容性。

多粒度锁:行锁(细粒度),表锁(粗粒度)。

对细粒度对象上锁,先对粗粒度对象上锁。

 

意向锁是表级别的锁,设计目的是为了在下一个事务揭示下一行将被请求的锁的类型。 

意向锁会阻塞全表扫描的请求,不会阻塞其他请求。

 一致性非锁定读

通过MVCC读取当前行的数据。如果当前事务对该行执行update,delete操作,不必等待锁的释放,通过读取锁的快照数据(通过undo段实现)。

在读已提交事务隔离级别下,读取该行最新一份快照数据。

在可重复读事务隔离级别下,读取的是该行事务开始时的行数据版本。

上面的不同是因为read review导致的。

一致性锁定读

对于select事务加上x锁或者s锁。

锁的算法

 Record Lock总是去锁住索引记录,如果没设置索引,InnoDB会对隐式的索引进行锁定。

在唯一索引中

 当查询的索引含有唯一的属性时,InnoDB存储引擎会对next_key lock降级为record_lock,仅锁住索引本身而不是范围。

 在辅助索引中

对于唯一键值的锁定,Next-Key Lock降级为Record Lock仅存在于查询所有的唯一索引列(唯一就是指索引值唯一无重复的,可以直接point查询)

唯一索引由多个列组成,而查询仅是查找多个唯一索引列中的其中一个,那么查询其实是range类型查询,而不是point类型查询,故InnoDB存储引擎依然使用Next-Key Lock进行锁定。

解决Phantom Problem

在默认的事务隔离级别下,即REPEATABLE READ 下,InnoDB存储引擎采用Next-Key Locking 机制来避免Phantom Problem (幻像问题即幻读)。

Phantom Problem是指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次的SQL语句可能会返回之前不存在的行。通俗一点:两次查同一范围,查询到的数据数目不同

解决方案:采用next_key lock对一个范围加上x锁。

 

锁问题

脏读

当前事务可以读到其他事务未提交的数据 

不可重复读

事务两次读同一个数据结果却不一样

和脏读的区别在于,脏读读到的是未提交的数据,不可重复读读到的是其他事务已经提交的数据

一般来说,不可重复读的问题是可以接受的,因为其读到的是已经提交的数据,本身并不会带来很大的问题。数据库事务的默认隔离级别设置为READ COMMITTED,在这种隔离级别下允许公
可重复读的现象。

在InnoDB存储引擎中,通过使用Next-Key Lock算法来避免不可重复读的问题。在MySQL官方文档中将不可重复读的问题定义为Phantom Problem,即幻像问题。在Next-Key Lock算法下,对于索引的扫描,不仅是锁住扫描到的索引,而且还锁住这些索引覆盖的范围(gap)。因此在这个范围内的插入都是不允许的。这样就避免了另外的事务在这个范围内插人数据导致的不可重复读的问题。因此,InnoDB存储引擎的默认事务隔离级别是READREPEATABLE,采用Next-Key Lock算法,避免了不可重复读的现象

丢失更新

一个事务的更新操作会被另外一个事务的更新操作所覆盖。

解决方案:让事务变成串行化,而不是并行化。即两个事务都加上x锁。

阻塞

一个事务中的锁等待另外一个事务释放它所占用的资源。

阻塞并不是坏事,而是为了确保事务可以并发正常进行。

InnoDB引擎大部分情况下不会对异常进行回滚。

死锁

两个或以上的事务在执行过程中因争夺锁资源而互相等待的现象。

最简单方法:将所有等待都回滚事务重新开始。

改进:超时,即当两个事务互相等待时,当一个等待时间超过设置的某一阈值时,其中一个事务进行回滚,另一个等待的事务就能继续进行。
超时机制虽然简单,但是其仅通过超时后对事务进行回滚的方式来处理,或者说其是根据FIFO的顺序选择回滚对象。但若超时的事务所占权重比较大,如事务操作更新了很多行,占用了较多的undo log,这时采用FIFO的方式,就显得不合适了,因为回滚这个事务的时间相对另一个事务所占用的时间可能会很多。

改进:当前数据库还都普遍采用wait-for graph(等待图)的方式来进行死锁检测。较之超时的解决方案,这是一种更为主动的死锁检测方式。InnoDB存储引擎也采用的这种方式。wait-for graph要求数据库保存以下两种信息:锁的信息链表,事务等待链表
通过上述链表可以构造出--张图,而在这个图中若存在回路,就代表存在死锁.

若存在则有死锁通常来说InnoDB存储引擎选择回滚undo量最小的事务。

死锁分类

如果程序是串行的,不可能产生死锁。死锁只产生在并发情况。

会话A等待会话B,B等待A,叫做AB--BA死锁

若发现死锁,会回滚一个事务。

另外一种死锁,即当前事务持有了待插入记录的下一个记录的X锁,但是在等待队列中存在一个S锁的请求,则可能会发生死锁。



锁升级

即将当前锁的粒度降低,行锁变页锁,页锁变表锁。为了减小锁的开销。





 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值