文章大纲

  • Undo日志
  • Redo日志
  • MVCC

Undo 日志

关系型数据需要实现事务的 ACID 特性,其中一点就是事务的原子性,Mysql 就是通过 Undo 日志就来实现的。

数据库处理数据都是先读到内存中,然后修改内存中的数据,最后将数据写回磁盘。

在事务处理过程中,操作数据之前会先将数据缓存至 Undo 日志,然后进行数据的修改。当事务回滚时,或者数据库奔溃时,系统可以利用 Undo 日志中的备份将数据恢复到事务开始之前的状态,撤销未提交事务对数据库产生的影响。

具体流程

假设有个用户表,字段有 id、name。

现需要将 id=1 的 name 修改为 kawaii,流程如下:

1、事务开始
2、将 id=1 的行数据记录到 undo log buffer
3、修改 id=1 的行数据 name 为 kawaii
4、undo log buffer 写入磁盘为 undo log file
5、将数据写入磁盘
6、事务提交

步骤 1 - 3 都是在内存中完成,第 4 步之前包括第 4 步如果出现问题,undo log 与数据都未写入磁盘,可以直接回滚,第 4 步之后出现问题,此时 undo log 已写入磁盘,利用 undo log 进行回滚。

对于insert操作,undo 日志记录新数据的 PK(ROW_ID),回滚时直接删除
对于delete/update操作,undo 日志记录旧数据,回滚时直接恢复

存在问题

事务提交时需要将内存中的数据同步写入磁盘,数据写入磁盘属于随机IO,性能较差,会极大影响数据库的吞吐量。

优化方案:将修改行为先写到 Redo 日志(顺序写),再定期将数据刷到磁盘上,这样能极大提高性能。

Redo 日志

Undo 日志存储的是历史数据快照,Redo 日志则存储最新数据。

具体流程

还是以上文中的操作为例:

1、事务开始
2、将 id=1 的行数据记录到 undo log buffer
3、修改 id=1 的行数据 name 为 kawaii
4、记录修改日志到 redo log buffer
5、undo log buffer 写入磁盘为 undo log file
6、redo log buffer 写入磁盘为 redo log file
7、事务提交

都是写磁盘,写 Redo 日志文件与直接写数据库文件有什么区别?

写 Redo 日志文件是顺序IO,而写数据库文件是随机IO,性能差别大。

Redo 日志文件写入成功后,数据库会另起线程将 Redo 日志写入数据库数据文件,实现持久化。

MVCC

MVCC(Multi-Version Concurrency Control)即多版本并发控制,Mysql、Oracle、PostgreSQL等数据库都实现了MVCC,但各自实现的机制不尽相同,因为MVCC没有统一的实现标准。

事务隔离级别

事务有四个隔离级别

  • 脏读:事务中的未提交的修改对其它事务是可见的。

如下表所示,事务B可以读取到事务A未提交的数据。

  • 重复读:事务中多次读取同一数据,结果不一致。

如下表所示,事务B两次读取之间事务A修改了数据并提交事务,事务B的第二次读取与第一次读取结果有变化。

  • 幻读:一个事务在读取某个范围内的记录时,另一个事务在该范围插入的新记录,之前事务再次读取该范围记录时,会产生幻行。

如下表所示,事务B两次读取之间事务A插入了一条数据并提交事务,事务B第二次读取 id < 5 的范围数据时,数量增加了。

什么是MVCC

InnoDB 存储引擎默认的事务隔离级别为 RR (可重复读)

那么 InnoDB 如何实现可重复读?加行级锁是肯定可以实现的,但如果对读操作也加行级锁,将严重影响数据库的并发性能,而MVCC 就是这个问题的解决方案。

MVCC 是一种用来解决读-写冲突的无锁并发控制,通过对行数据的多版本控制,避免了读操作时的加锁操作,因此开销更低,大大提高数据库系统的并发性能。

InnoDB 就是通过 行级锁+MVCC 共同实现事务隔离,正常读的时候不加锁,写的时候对数据行加排它锁。

MVCC 只能在 Read Committed 和 Repeatable Read 两个隔离级别下工作。

MVCC实现原理

存储结构

InnoDB 支持聚簇索引,默认设置主键列为聚簇索引,如果表中无主键,则会选择一个唯一的非空索引作为聚簇索引,如果也没有,则会隐式定义一个主键作为聚簇索引。

InnoDB 的数据行存储在聚簇索引上,结构如下:

可以看到索引上不仅存储了索引列、行数据,还包含了两个隐藏字段:

  • DB_TRX_ID(6字节):表示最近一次修改(insert | update)的事务ID。
  • DB_ROLL_PTR(7字节):回滚指针,指向这条记录的上一个版本(存储于 roolback segment 里的 update undo log)

还有一个删除 flag 隐藏字段,delete 操作被认为是一个 update 操作,只是修改了该删除标记位,而不是物理删除。

以上文中的表结构为例:

第一步:事务1,插入一条记录

第二步:事务2,修改 name 为 kawaii,流程如下

1、事务开始,对数据行加排它锁
2、将该行数据记录到 undo log,事务ID 为 1 的数据行
3、修改该行数据 name 为 kawaii,DB_TRX_ID 修改为 2,DB_ROLL_PTR 指向 步骤 2 中记录的 undo log
4、提交事务,释放排它锁

当前最新数据如下,其中 0x23636355 指向 undo log 中 DB_TRX_ID 为 1 的地址

第三步:事务3,修改 name 为 unknown,流程如下

1、事务开始,对数据行加排它锁
2、将该行数据记录到 undo log,事务ID 为 2 的数据行
3、修改该行数据 name 为 unknown,DB_TRX_ID 修改为 3,DB_ROLL_PTR 指向 步骤 2 中记录的 undo log
4、提交事务,释放排它锁

当前最新数据如下,其中 0x65461234 指向 undo log 中 DB_TRX_ID 为 2 的地址

可以看出,通过 DB_ROLL_PTR 指针,同一行数据的多个版本形成了一个单向链表,链表中除第一条记录,都存储在 undo log。

ReadView 结构

通过 undo log 实现数据的多版本存储,接下来需要处理的就是数据读取的问题,该读取哪个版本的数据?ReadView 就是用来做可见性判断的。

ReadView 结构有几个重要的变量

  • creator_trx_id:当前事务的ID,每个事务都会拥有一个ID,是一个递增的编号。
  • trx_ids:Read View创建时其他未提交的活跃事务ID列表。
  • low_limit_id:目前出现过的最大的事务ID+1,即下一个将被分配的事务ID。
  • up_limit_id:活跃事务列表 trx_ids 中最小的事务ID,如果 trx_ids为空,则 up_limit_id 为 low_limit_id。

InnoDB 会在事务执行第一个 select 语句的时候创建 ReadView,读取某行记录的时候,根据该行的DB_TRX_ID 与 ReadView 进行可见性分析,判断读取哪个版本的数据。

具体的可见性比较算法如下:

  • 判断 DB_TRX_ID < up_limit_id,如果成立,表明 最新修改该行的事务当前事务 创建 ReadView 之前就已经提交,所以 DB_TRX_ID 版本对 当前事务 是可见的,否则进入下一个判断
  • 判断 DB_TRX_ID >= low_limit_id,如果成立,表明 最新修改该行的事务当前事务 创建 ReadView 之后才修改该行,所以DB_TRX_ID 版本对 当前事务 是不可见的
  • 判断 DB_TRX_ID 是否在活跃事务列表 trx_ids 中如果在,表明在 当前事务 创建 ReadView 时,最新修改该行的事务 还在活跃中,尚未提交,所以 DB_TRX_ID 版本对 当前事务 是不可见的。如果不在,表明在 当前事务 创建 ReadView 之前,最新修改该行的事务 就已经提交,所以 DB_TRX_ID 版本对 当前事务 是可见的。
  • DB_TRX_ID 版本对 当前事务 不可见,则根据 DB_ROLL_PTR 取出上一个版本数据,使用其 DB_TRX_ID 重新判断一次。

看完规则后,也许脑瓜子是嗡嗡的,那么接下来做一个模拟分析

事务2 执行快照读时,数据库为该行数据创建一个 ReadView,此时事务1、3处于活跃状态,事务4已提交,那么 ReadView 中各个变量的值如下:

trx_ids = [1,3]low_limit_id = 4 + 1 = 5up_limit_id = 1123

事务2读取最新记录,该记录的 DB_TRX_ID = 4,根据上文中的规则

  • 判断 DB_TRX_ID < up_limit_id,不成立,下一步
  • 判断 DB_TRX_ID >= low_limit_id,也不成立,下一步
  • 判断 DB_TRX_ID 是否在 trx_ids 集合中,结果为否,符合可见性条件。

所以事务4提交的最新结果对事务2是可见的。

再来一个更复杂的模拟分析,原始金额为 500,DB_TRX_ID 为 100

MVCC实现RR/RC事务隔离级别

前文中给出的示例都是基于 RR 隔离级别,下文给出一个 RR 隔离级别的简单示例,方便与 RC 隔离级别进行比较。

RR 隔离级别

RC 隔离级别

都是使用 MVCC 进行实现,同样的操作需要得到不同的结果,区别就在于创建 ReadView 的时机,RR 隔离级别只在第一个 select 语句时创建,而 RC 隔离级别则是每一个 select 语句都创建。

mininet编程实现交换机规则的插入、删除与修改。_Mysql闲聊之从Redo、Undo日志到MVCC实现原理相关推荐

  1. mininet编程实现交换机规则的插入、删除与修改。_Mysql事务隔离以及MVCC实现原理...

    上一篇我们了解了mysql的几种日志,大致知道这些日志的作用,今天我们配合Mysql的事务以及事务的隔离级别进一步理解mysql如何实现事务相关的特性.其中重点理解mysql innodb的多版本控制 ...

  2. mininet编程实现交换机规则的插入、删除与修改。_可编程网卡芯片在滴滴云网络的应用实践...

    桔妹导读:随着云规模不断扩大以及业务层面对延迟.带宽的要求越来越高,采用DPDK 加速网络报文处理的方式在横向纵向扩展都出现了局限性.可编程芯片成为业界热点.本文主要讲述了可编程网卡芯片在滴滴云网络中 ...

  3. Access SQL语法(查询/插入/删除/连接/修改)

    SQL语法 1. 查询 简单查询 select 班级,姓名,性别 from 学生名单 加筛选条件 select 班级,姓名,性别 from 学生名单 where 性别="女" 分组 ...

  4. 更新和插入的并发问题_mysql经典面试题:如何读写分离?主从原理是啥?同步的延时问题...

    面试题 你有没有做 MySQL 读写分离?如何实现 MySQL 的读写分离?MySQL 主从复制原理的是啥?如何解决 MySQL 主从同步的延时问题? 考点分析 高并发这个阶段,肯定是需要做读写分离的 ...

  5. iptables规则的查看、添加、插入、删除和修改

    1.查看 iptables -nvL –line-number -L 查看当前表的所有规则,默认查看的是filter表,如果要查看NAT表,可以加上-t NAT参数 -n 不对ip地址进行反查,加上这 ...

  6. iptables规则的查看、添加、删除和修改

    1.查看 iptables -nvL --line-number -L 查看当前表的所有规则,默认查看的是filter表,如果要查看NAT表,可以加上-t NAT参数 -n 不对ip地址进行反查,加上 ...

  7. 进程句柄表初始化,扩展,插入删除句柄源码分析

    一.为什么要有句柄 句柄是一个8字节的结构体,用途是指向内核对象.3环程序无法通过地址直接访问内核对象,所以需要用句柄来间接访问. 本文重点介绍句柄表,句柄本身则留到下一篇博客介绍.但因为接下来介绍句 ...

  8. firewalld/iptables防火墙维护和状态查询命令(防火墙重载,区域操作命令,开启服务或端口,堵塞端口,iptables规则添加和删除)

    文章目录 firewalld防火墙维护和状态查询命令 firewalld防火墙状态查询命令 firewalld防火墙重载配置命令 重新加载firewalld的配置 查询预定义信息命令 firewall ...

  9. Mininet系列实验(六):Mininet动态改变转发规则实验

    Mininet系列实验(六):Mininet动态改变转发规则实验 一. 实验目的 熟悉Mininet自定义拓扑脚本的编写: 熟悉编写POX脚本动态改变转发规则 二.实验原理 在SDN环境中,控制器可以 ...

最新文章

  1. java tree degree_生成树计数-Matrix-Tree定理
  2. Asp.Net读写XML简单方法
  3. Maven无法上传到到私服
  4. android dialog 结构,Android 原生Dialog实现
  5. 数据结构实验四 排序算法的实现
  6. 企业正确进行数字化转型的7个秘诀
  7. 局域网如何找路由器外的计算机,用路由组建小局域网,怎么使局域网之外的计算机共享到打印机?...
  8. gamma 函数的 LaTeX 代码
  9. HFSS天线设计过程学习笔记
  10. UTM投影的选择(地区-投影带)
  11. 离散ziggurat算法python实现_SLAM的数学基础(3):几种常见的概率分布的实现及验证。...
  12. 使用JAVA对数据库的记录进行操作(初步)
  13. 关于1NF、2NF、3NF、BCNF范式
  14. c语言编程求pai的近似值,c语言:求π的近似值
  15. 生容易,活容易,生活不容易
  16. win8.1环境下硬盘安装centos6.5双系统
  17. GSA 8月最新5G报告:全球已发布100台5G设备
  18. 计算机技术在图形图像处理中的应用,计算机技术在图形图像处理中的应用研究...
  19. 被遗忘的Windows快捷键
  20. Python黑客攻防(八)密码破解攻击

热门文章

  1. 程序结构程序设计(二)
  2. 假设检验——抽样调查的结论依赖于样本量的大小
  3. STL::算法::常见算法
  4. python是什么语言-Python是什么?为什么现在越来越多的人选择学习Python语言
  5. 用python画玫瑰花-用python画一朵玫瑰花
  6. 学python需要什么基础-自学Python需要怎样的基础和准备
  7. python使用-python 类如何使用
  8. python一对一视频教学-使用Python的Tornado框架实现一个一对一聊天的程序
  9. 自学python买什么书比较好-python入门学习哪个书比较好(python视频教程知乎)
  10. 消费者生产者代码之---一步一步带你写