当前读:select...for update(delete)、update.....、delete.....这些操作,当前读的隔离级别是通过加锁实现的。
快照读:普通的select.....。快照读的隔离级别是通过mvcc实现的。
在学习这一块内容的时候是非常折磨得,因为这一块涉及到的内容太多太乱所以一直也理不清思路,今天又看了一篇文章后才稍微有些思路,下面我会用大白话进行叙述,如果有看到这篇文章的小伙伴,可以对我说的不对的地方进行评论,我会去改正,谢谢大家!
首先事物就是:一组不可分割的操作的序列。具有ACID四大特性。
四大特性中的: 原子性是靠undo log日志来实现的(具体实现就不细说了)。
持久性是靠redoLog日志实现的。
隔离性可以通过加锁或者mvcc进行实现。
一致性是由以上三者共同实现的。
接着:
事物的隔离级别从字面就能看出来是隔离性相关的。因为mysql数据库允许多个事物并发的进行操作不同或者相同的一段数据,所以导致可能会出现(脏写,脏读,不可重复读,幻读的问题)。为了解决这几个问题并且同时兼顾性能问题,所以目前innodb搜索引擎支持了四种不同的隔离级别来解决这几个问题。
基础的知识默认大家已经知道了,接下来开始正片。
首先我们可以通过加锁来实现四种事务隔离级别:举个例子,比如只有在写的时候加X锁(实现:读已提交),只有读的时候加S锁,在写的时候加X锁(实现:可重复度隔离级别)。
这种方式加锁的方式可以实现但是加锁就会导致其他的事物不能用锁住的数据,导致性能变差,并发能力下降。所以就有一种方法叫做mvcc来替换掉加锁的方案。
mvcc:他是同过undolog日志和readview这两者结合来实现事物的隔离级别(具体实现可以搜一下),大致原理:就是一行数据维护多个版本,我们通过读取不同的版本来达到和加锁一样的效果。
inndb引擎默认是在可重复读这一隔离级别下的,依然会存在幻读问题(幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。)
既然默认的隔离级别可能存在幻读,我们要去想办法解决,这时候就用到行锁里面的间隙锁和临键锁。也就是我们在查询的时候手动加上锁(
SELECT `id` FROM `users` WHERE `id` = 1 FOR UPDATE;
)像这样手动加上锁之后,在可重复读这个级别下也可以避免幻读问题。当然加锁的时候还涉及到(行锁优化为间隙锁之类的就不细说了)。