Mysql的 MVCC和隔离级别RR,RC介绍

一.首先介绍一下最基本的事务几个概念:

1.脏读: 读到了别人未提交的数据,数据有可能会发生回滚,所以是脏读

2.可重复读: 在同一个事务中,多次读取同一条数据,读取结果是一致的,通常对应的是更新操作

3.不可重复读: 在同一个事务中,多次读取同一条数据,有可能读取结果是不一致的,读取到了别人更新数据

4.幻读: 在同一个事务中,多次读取同一条数据,有可能读取结果是不一致的,读取到了别人插入的数据

二.事务的四大特性:

分别是原子性、一致性、隔离性、持久性。

1、原子性(Atomicity)

原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

2、一致性(Consistency)

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。举例来说,假设用户A和用户B两者的钱加起来一共是1000,那么不管A和B之间如何转账、转几次账,事务结束后两个用户的钱相加起来应该还得是1000,这就是事务的一致性。

3、隔离性(Isolation)

隔离性是当多个用户并发访问数据库时,比如同时操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。

4、持久性(Durability)

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务已经正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成。否则的话就会造成我们虽然看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。这是不允许的。

三.介绍基本的四种隔离级别

mysql默认隔离级别是: 可重复度

四.Mysql的 MVCC机制:

MVCCMySQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读,而这个读指的就是快照读,同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题

1.MySQL InnoDB下的当前读和快照读

    ①当前读
    像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁

   ②快照读
    像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

2.它的实现原理主要是依赖记录中的 3个隐式字段undo日志Read View 来实现的

3.mysql中每行数据除了我们自定义的字段外,还有3个隐式字段

DB_TRX_ID:最近修改(修改/插入)事务ID:记录创建这条记录/最后一次修改该记录的事务ID

DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本(存储于rollback segment里)

DB_ROW_ID:隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引

实际还有一个删除flag隐藏字段, 既记录被更新或删除并不代表真的删除,而是删除flag变了

4.undo日志:

insert undo log:代表事务在insert新记录时产生的undo log, 只在事务回滚时需要,并且在事务提交后可以被立即丢弃

update undo log:事务在进行updatedelete时产生的undo log; 不仅在事务回滚时需要,在快照读时也需要;所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一清除

对MVCC有帮助的实质是update undo logundo log实际上就是存在rollback segment中旧记录链

5.当一个事务对当前行进行修改的时候:

①数据库会首先加一个排它锁

②在把他写到undo log日志里面

③进行数据修改,同时把隐藏的事务id加1,回滚id指向旧数据的副本记录

④事务提交后,释放锁

不同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,既链表,undo log的链首就是最新的旧记录,链尾就是最早的旧记录

6.read view (读视图)

Read View就是事务进行快照读操作的时候生产的读视图(Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID

即当我们某个事务执行快照读的时候,对该记录创建一个Read View读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据

Read View遵循一个可见性算法

将要被修改的数据当前事务ID取出来与系统当前其他活跃事务的ID去对比(由Read View维护)

比如:

当前并发的所有修改事务线程都没有提交,不符合可见性,那就通过回滚指针去取出Undo Log中的DB_TRX_ID再比较,即遍历链表(即从最近的一次修改查起),直到找到满足特定条件的DB_TRX_ID, 那么这个DB_TRX_ID所在的旧记录就是当前事务能看见的最新老版本

如果当前并发的所有事务中,其中一个事务快照读前一刻提交更新了,那么这个事务提交的数据符合可见性条件.就会查询出来这条事务修改的数据.

五.Mysql中隔离级别RR和RC的区别

RC 和 RR 唯一的区别在于“是否可重复读”在一个事务执行过程中,它能不能读到其他已提交事务对数据的更新,如果能读到数据变化,就是“不可重复读”,否则就是“可重复读”

正是Read View生成时机的不同,从而造成RC,RR级别下快照读的结果的不同

1.在RR级别下的某个事务的对某条记录的第一次快照读会创建一个快照及Read View, 将当前系统活跃的其他事务记录起来,此后在同一个事务中再次进行同一行数据进行快照读的时候,还是使用的是同一个Read View,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用的都是同一个Read View,所以对之后的修改不可见;而早于Read View创建的事务所做的修改均是可见

2.而在RC级别下的,再同一个事务中,每次快照读都会新生成一个快照和Read View, 这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因

3.总之在RC隔离级别下,是每个快照读都会生成并获取最新的Read View;而在RR隔离级别下,则是同一个事务中的第一个快照读才会创建Read View, 之后的快照读获取的都是同一个Read View。

4.RC的性能比RR好,因为他允许存在幻读和不可重复读,mysql默认的是RR隔离级别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值