Mysql 事务和MVCC简单说明

Mysql 事务和MVCC简单说明

事务应该具有的四个特性(ACID)

原子性(Atomicity): 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
一致性(Consistency): 执行事务后,数据库从一个正确的状态变化到另一个正确的状态;
隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

并发事务可能出现的问题

  • 脏读: 当一个事务正在访问数据并且对数据进行了修改,而修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,读到了没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”。

  • 丢失修改: 指的是多个事务修改同一个数据,然后假设有一个事务需要滚,就将其他事务将这行的修改给破坏了

  • 不可重复读: 指一个事务在事务期间内,多次读取的数据是不一样的,由于其他事务修改数据导致。(同一个记录)

  • 幻读: 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。(多条记录)

注意:不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。

四个隔离级别

  • READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
  • READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
  • REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  • SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

MVCC : 多版本控制

一种提高并发的技术,不同的数据库之间可能有不停的实现,没有统一的实现标准,Mysql中的InnoDB是在undolog中实现的,通过undolog可以找回数据的历史版本。找回的数据历史版本可以提供给用户读(按照隔离级别的定义,有些读请求只能看到比较老的数据版本),也可以在回滚的时候覆盖数据页上的数据。在InnoDB内部中,会记录一个全局的活跃读写事务数组,其主要用来判断事务的可见性

  • Mysql 中由事务型存储引擎InnoDB支持
  • MVCC 在高并发事务下比单纯的加锁高效
  • 只在读已提交和可重复读两个隔离级别下有效
  • InnoDB存储引擎在数据库每行数据的后面添加了三个字段 官网

InnoDB向数据库中存储的每一行添加三个字段。

  • DB_TRX_ID字段:6字节, 表示插入或更新该行的最后一个事务的事务标识符。此外,删除在内部被视为更新,在该更新中,行中的特殊位被设置为将其标记为已删除。
  • DB_ROLL_PTR字段:7字节,称为滚动指针。回滚指针指向写入回滚段的撤消日志记录。如果行已更新,则撤消日志记录将包含在更新行之前重建行内容所必需的信息。
  • DB_ROW_ID字段:行ID,该行ID随着插入新行而单调增加。如果 InnoDB自动生成聚集索引,该索引包含行ID值。否则,该 DB_ROW_ID列不会出现在任何索引中。

read view (活跃的其他事务记录记录起来) 主要是用来做可见性判断的,read view快照的生成时机不同, 造成了RC,RR两种隔离级别的不同可见性

  • repeatable read:在begin/start transaction之后的第一条select读操作后, 会创建一个快照(read view), 将当前系统中活跃的其他事务记录记录起来
  • read committed级别: 事务中每条select语句都会创建一个快照(read view);

Undo log : InnoDB MVCC事务特性的重要组成部分。对记录做了变更操作时就会产生undo记录,存储旧版本数据,旧事务读取数据时,为满足隔离级别可以顺着undo链找到响应的数据

  • insert undo log :事务insert操作产生,只在事务回滚需要,事务提交后丢弃
  • update undo log : 事务delete 和 update 操作产生,回滚和事务隔离时(一致性)需要,不能随便删除

判断逻辑
read view 事务id 集合(活跃的),最小值 up_limit_id ,最大值low_limit_id(系统下一个事务要分配的id)

首先比较 DB_TRX_ID < up_limit_id , 如果小于,则当前事务能看到 DB_TRX_ID 所在的记录,如果大于等于进入下一个判断
接下来判断 DB_TRX_ID >= low_limit_id , 如果大于等于则代表 DB_TRX_ID 所在的记录在 Read View 生成后才出现的,那对当前事务肯定不可见,如果小于则进入下一个判断
判断 DB_TRX_ID 是否在活跃事务之中,trx_list.contains (DB_TRX_ID),如果在,则代表我 Read View 生成时刻,你这个事务还在活跃,还没有 Commit,你修改的数据,我当前事务也是看不见的;如果不在,则说明,你这个事务在 Read View 生成之前就已经 Commit 了,你修改的结果,我当前事务是能看见的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值