MySQL 事务和MVCC原理

       事务定义

   事务是一组操作,这些操作可以是一条SQL语句、一组SQL语句或整个程序。

           什么时候会用到事务呢?当多张强一致关联的表,需要进行数据同步的时候,就需要开启事务

 

  事务特性

  •  原子性 (atomicity): 强调事务的不可分割.最小执行逻辑单位。事务只会全部成功或全部失败。
  •  一致性 (consistency): 事务的执行的前后数据的完整性保持一致。这是基于原子性做到的。
  •  隔离性 (isolation): 一个事务执行的过程中,不应该受到其他事务的干扰。
  •  持久性(durability) : 事务一旦结束,数据就持久到数据库。

 

  事务隔离级别

   

  

      建议的隔离级别

    建议使用读已提交(RC)。从性能上考虑:

  •     RR比RC多使用间隙锁,死锁概率高 (RR会使用记录锁和间隙锁。间隙锁:锁定一个范围,不包含记录本身,防止其他事务增删造成二次查询的数据有差异,解决不可重复读问题)
  •     使用不了索引会锁表

      从逻辑上说,每次读到最新提交的数据,也符合正常思维。

 

    MVCC原理

     MVCC(Multiversion concurrency control) 就是同一份数据保留多版本的一种方式,进而实现并发控制(事务并发)通过undo log版本链和read view实现

 

         undo log 版本链

          MVCC 的实现依赖于版本链,版本链是通过表的三个隐藏字段实现。

  • DB_TRX_ID:当前事务id,通过事务id的大小判断事务的时间顺序。
  • DB_ROLL_PTR:回滚指针,指向当前行记录的上一个版本,通过这个指针将数据的多个版本连接在一起构成undo log版本链。
  • DB_ROW_ID:主键,如果数据表没有主键,InnoDB会自动生成主键。    

         新增一条表记录大概是这样的:

         insert into test (name,age) values (duiker,12);

       

        当事务更新该记录的时候,会生成undo log。执行过程如下:

  1.排它锁锁住行

       2.复制一份数据到undo log。

       3.修改当前行的值。生成一个新版本,回滚指针指向该条undo log的地址。

  执行结果如下:

  update test set name = duikerdd where name = duiker;

       

       4.此时undo log有一条数据。

 

        read view 快照

         read view可以理解成将数据在某个时刻的状态拍成“照片”记录下来

   read view内部维护一个活跃事务链表,表示快照的活跃事务这个链表包含在创建read view之前还未提交的事务不包含创建read view之后提交的事务
不同隔离级别,read view生成时机也不同:
  • RC:每次执行select都会创建新的read_view,保证能读取到其他事务已经提交的修改。
  • RR:在一个事务范围内,第一次select时更新这个read_view,以后不会再更新,后续所有的select都是复用之前的read_view。这样可以保证事务范围内每次读取的内容都一样,即可重复读。
         read view的记录筛选方式
   前提:DATA_TRX_ID 表示每个数据行的最新的事务ID;up_limit_id表示当前快照中的最先开始的事务;low_limit_id表示当前快照中的最慢开始的事务,即最后一个事务。
  •    如果DATA_TRX_ID < up_limit_id:说明在创建read view时,修改该数据行的事务已提交,该版本的记录可被当前事务读取到。  
  •      如果DATA_TRX_ID >= low_limit_id:说明当前版本的记录的事务是在创建read view之后生成的,该版本的数据行不可以被当前事务访问。此时需要通过版本链找到上一个版本,然后重新判断该版本的记录对当前事务的可见性。
  •      如果up_limit_id <= DATA_TRX_ID < low_limit_i:需要在活跃事务链表中查找是否存在ID为DATA_TRX_ID的值的事务。如果存在,因为在活跃事务链表中的事务是未提交的,所以该记录是不可见的。此时需要通过版本链找到上一个版本,然后重新判断该版本的可见性。如果不存在,说明事务trx_id 已经提交了,这行记录是可见的。

  总结InnoDB 的MVCC是通过 read view 和undo log版本链实现的,版本链保存有历史版本记录,通过read view 判断当前版本的数据是否可见,如果不可见,再从版本链中找到上一个版本,继续进行判断,直到找到一个可见的版本

  这样在多个事务中,可以同时读到相应的可见数据。 从而实现了事务并发控制。

 

 

posted @ 2023-02-11 14:48  Duikerdd  阅读(40)  评论(0编辑  收藏  举报