[ MySQL] 数据库的隔离级别和MVCC

数据库存在4种事务隔离级别(重低到高)
使用不同隔离级别可能会出现的问题
使用不同隔离级别可能会出现的问题

1.读未提交(read uncommitted)
一个事务还没提交时,它做的变更就能被别的事务看到!

2.读已提交(read commited)
一个事务提交之后,它做的变更才会被其他事务看到。

解决方案:读已提交就是改变了释放锁的时机,让事务完成提交后再去释放锁

3.可重复读(repeatable read)
一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。

解决方案:不可重复读就是在两次读取的数据不一致,那我们就要保证一个事务读取数据的时候就让它老老实实读那个数据,可重复读是用一个MVCC(多版本并发控制)机制去解决的

4.串行化(serializable)
对于同一行记录,“写”会加“写锁”,“读”会加“读锁”,当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

那么,为什么不直接把隔离级别设置为串行化,不就可以避免所有的问题?
隔离级别越高,并发效果越差,甚至造成死锁这种麻烦

数据库的隔离级别在解决哪些问题
1.脏读(dirty read)
如果一个事务读到了另一个未提交事务修改过的数据。
脏读
理解:一个事务读取到了另一个还未提交事务的数据,所以把隔离级别调整为读提交,一个事务读取到的数据一定是另一个事务已经提交了的

2.不可重复读(non-repeatable read)
如果一个事务只能读到另一个已经提交的事务修改过的数据,并且其他事务每次对该数据进行一次修改并提交后,该事务都能查询得到最新值。
不可重复读
理解:一个事务读取数据时,读取到了别的事务插入的数据,导致前后数据读取不一致(在一个事务内对某条数据读两次)

3.幻读(phantom read)
如果一个事务先根据某些条件查询出一些记录,之后另一个事务又向表中插入了符合这些条件得记录,原先的事务再次按照该条件查询时,能把另一个事务插入的记录也读出来。

幻读
理解:幻读和不可重复读差不多,幻读主要是指查询的记录条数不一致,不可重复读主要指的是单个行数的数据读取不一致

如何设置事务的隔离级别?
可以通过下边的语句修改事务的隔离级别:
set [global|session] transaction isolatton level level;

MVCC(多版本并发控制)
MVCC是一个行级锁的一个升级版,我们都知道数据库中有表锁和行锁,在表锁中读写操作是阻塞的,而MVCC读写一般是不会阻塞的,这样避免了很多加锁的过程。

具体实现:通过在每行记录后面的保存两个隐藏的字段,一个保存的是此行的创建时间,一个保存的是此行的过期时间。它们存储的也并不是真的时间,而是系统版本号。就跟我们使用软件有1.0,2.0这些版本,每个版本有它们自己的特点和数据

MVCC把sql分为两类:
一种是快照读:读的是历史版本的数据
一种是当前读:读的是最新的数据
(不可重复读就是利用快照保存数据)

通俗的说就是:MVCC就是给每次事务操作的数据行都加个字段,代表这次事务的版本,那么如果我现在读取这行数据时,就会通过这个版本生成一个数据快照,那么我这个事务再读的时候,会直接从版本快照中获得数据,相当于帮我们缓存了一份数据,这两次读取都是同一个事务喔!

解决幻读(使用串行化)

这里又要重申幻读和不可重复读的区别,不可重复读是针对某行数据,幻读是特指查询到记录条数,也就是多条数据的查询
所以我们使用MVCC+next-key lock锁去解决幻读问题

这里讲一下innodb的三种行锁的算法
1.行锁:就是对单条记录上锁
2.间隙锁:锁定一个范围,但是不会包括记录自己,例如要查询一个id=10的数据时,就会把它范围外的加上锁防止插入数据操作,这个就是间隙锁。
3.Next-key lock:行锁+间隙锁的合体算法,使用它时不仅会把id=10的范围加上行锁,也会把它的间隙加上锁,对于行的查询,使用此法就能够解决。

总结
解决脏读:改变锁的释放时机,使用"读已提交"事务隔离方案,让事务完成提交后再释放。

解决不可重复读:MVCC机制,事务查询时相应保存一个事务版本号,然后保存查询的数据快照,期间不管其他事务怎么修改数据 ,本事务读的还是一样的数据。

解决幻读: MVCC+Next-key Lock锁查询时对范围加锁,期间其他事务不能修改数据,保证数据读取一致性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值