MySQL事务特性及实现原理
MySQL事务详解
什么是事务
简单来说,事务是指逻辑上的一组操作,要么全都执行,要么全部执行失败。
举个栗子:事务最常见的例子就是转账了。假如小红要给小明转1000元,转账会涉及两个关键的步骤:
- 小红的账户减少1000元。
- 小明的账户增加100元。
事务会把这两个操作看成逻辑上的一 个整体,要么这个整体包含的操作都成功,要么都失败。这样就不会出现小红账户余额减少了,小名账户余额却没有增加。
事务的四个特性(ACID)
关系型数据库(例如:MySQL
、SQL Server
、Oracle
等)事务都有 ACID 特性:
- 原子性(Atomicity):事务是最小的执行单位不允许分割。事务的原子性确保动作要么全都成功,要么失败回滚。
- 一致性(Consistency):事务执行前后,数据保持一致。例如转账业务,无论操作是否成功,转账者和收款者的账户总额是不变的。
- 隔离性(Isolation):多个事务并发访问数据库时,一个事务不受其他事务的影响,各个并发事务之间数据库是独立的。
- 持久性(Durability):一个事务提交之后,对数据库中数据的改变是持久的,即使数据库发生故障也不会对其产生任何的影响。
事务的隔离级别
并发事务带来的问题
- 脏读: 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
- 不可重复读:指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读 。
- 幻读:幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
- 丢失修改:指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务 1 读取某表中的数据 A=20,事务 2 也读取 A=20,事务 1 修改 A=A-1,事务 2 也修改 A=A-1,最终结果 A=19,事务 1 的修改被丢失。
事务的隔离级别
- READ-UNCOMMITTED(读取未提交):最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
- READ-COMMITTED(读取已提交):允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
- REPEATABLE-READ(可重复读):对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- SERIALIZABLE(可串行化) 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ-UNCOMMITTED | ✔ | ✔ | ✔ |
READ-COMMITTED | x | ✔ | ✔ |
REPEATABLE-READ | x | x | ✔ |
SERIALIZABLE | x | x | x |
MySQL 的默认隔离级别是什么
MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。我们可以通过SELECT @@tx_isolation;
命令来查看,MySQL 8.0 该命令改为SELECT @@transaction_isolation;
因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 READ-COMMITTED(读取提交内容) ,但是你要知道的是 InnoDB 存储引擎默认使用 REPEATABLE-READ(可重读) 并不会有任何性能损失。
InnoDB 存储引擎在 分布式事务 的情况下一般会用到 SERIALIZABLE(可串行化) 隔离级别。
事务实现的原理
A原子性由undo log(回滚日志)日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql。
C一致性由其他三大特性保证、程序代码要保证业务上的一致性
I隔离性由MVCC来保证。
D持久性由内存+redo log(重做日志)来保证,mysql修改数据同时在内存和redo log记录这次操作,宕机的时候可以从redo log恢复。
InnoDB redo log 写盘,InnoDB 事务进入 prepare 状态。 如果前面 prepare 成功,binlog 写盘,再继续将事务日志持久化到 binlog,如果持久化成功,那么InnoDB 事务则进入 commit 状态(在 redo log 里面写一个 commit 记录)。
redolog的刷盘会在系统空闲时进行。
什么是MVCC
多版本并发控制:读取数据时通过一种类似快照的方式将数据保存下来,这样读锁就和写锁不冲突了,不同的事务session会看到自己特定版本的数据,版本链。
MVCC
的实现依赖于:隐藏字段、Read View、undo log。在内部实现中,InnoDB
通过数据行的 DB_TRX_ID
和 Read View
来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR
找到 undo log
中的历史版本。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 Read View
之前已经提交的修改和该事务本身做的修改。
在内部,InnoDB存储引擎,为每行字段添加了三个隐藏字段。
DB_TRX_ID:表示最后一个插入或者更新这行事务的id。delete操作在内部被视为更新,只不过会在记录头Record Header记录投中的deleted_flag将其标记为已删除。
DB_ROLL_PTR:回滚指针。指向该行的undo log,如果没有被更新,则为空。
DB_ROW_ID:如果没有设置主键且表没有创建唯一非空索引时,InnoDB会用该id来生成聚簇索引。
Read View
class ReadView {/* ... */
private:trx_id_t m_low_limit_id; /* 大于等于这个 ID 的事务均不可见 */trx_id_t m_up_limit_id; /* 小于这个 ID 的事务均可见 */trx_id_t m_creator_trx_id; /* 创建该 Read View 的事务ID */trx_id_t m_low_limit_no; /* 事务 Number, 小于该 Number 的 Undo Logs 均可以被 Purge */ids_t m_ids; /* 创建 Read View 时的活跃事务列表 */m_closed; /* 标记 Read View 是否 close */
}
Read View
主要是用来做可见性判断,里面保存了 “当前对本事务不可见的其他活跃事务”。
m_low_limit_id
:目前出现过的最大的事务 ID+1,即下一个将被分配的事务 ID。大于等于这个 ID 的数据版本均不可见。
m_up_limit_id
:活跃事务列表 m_ids
中最小的事务 ID,如果 m_ids
为空,则 m_up_limit_id
为 m_low_limit_id
。小于这个 ID 的数据版本均可见。
m_ids
:Read View
创建时其他未提交的活跃事务 ID 列表。创建 Read View
时,将当前未提交事务 ID 记录下来,后续即使它们修改了记录行的值,对于当前事务也是不可见的。m_ids
不包括当前事务自己和已提交的事务(正在内存中)。
m_creator_trx_id
:创建该 Read View
的事务 ID。
数据可见性
在 InnoDB
存储引擎中,创建一个新事务后,执行每个 select
语句前,都会创建一个快照(Read View),快照中保存了当前数据库系统中正处于活跃(没有 commit)的事务的 ID 号。其实简单的说保存的是系统中当前不应该被本事务看到的其他事务 ID 列表(即 m_ids)。当用户在这个事务中要读取某个记录行的时候,InnoDB
会将该记录行的 DB_TRX_ID
与 Read View
中的一些变量及当前事务 ID 进行比较,判断是否满足可见性条件。
- 开始事务时创建readview,readView维护当前活动的事务id,即未提交的事务id,排序生成一个数组。
- 访问数据,获取数据中的事务id(获取的是事务id最大的记录),对比readview。
- 如果在readview的左边(比readview都小),可以访问(在左边意味着该事务已经提交)。
- 如果在readview的右边(比readview都大)或者就在readview中,不可以访问,获取roll_pointer,取上一版本重新对比(在右边意味着,该事务在readview生成之后出现,在readview中意味着该事务还未提交)。
这就是Mysql的MVCC,通过版本链,实现多版本,可并发读-写,写-读。通过ReadView生成策略的不同实现不同的隔离级别。
已提交读和可重复读的区别就在于它们生成ReadView的策略不同。
在事务隔离级别 RC
和 RR
(InnoDB 存储引擎的默认事务隔离级别)下,InnoDB
存储引擎使用 MVCC
(非锁定一致性读),但它们生成 Read View
的时机却不同
- 在 RC 隔离级别下的
每次select
查询前都生成一个Read View
(m_ids 列表) - 在 RR 隔离级别下只在事务开始后
第一次select
数据前生成一个Read View
(m_ids 列表)
MySQL事务特性及实现原理相关推荐
- 最详细的MySQL事务特性及原理讲解!(一)
点击上方"后端开发技术",选择"设为星标" ,优质文章和资源,及时送达 我们将事务这块内容分为两篇来讲,这篇主要是事务的特性和原理. 接着看文章,如果对你有帮助 ...
- MySQL事务处理特性的实现原理
摘要:事务这个词来自于英语中的transactional这个词的翻译,这个词的含义更多的是指 "交易".在数据库系统或者软件系统中我们通常 称 transactional 为事务 ...
- mysql 事务隔离级别实现原理_MySQL事务隔离级别和实现原理 - 米扑博客
开发中经常提到数据库的事务,那你知道数据库还有事务隔离的说法吗, 事务隔离还有隔离级别,那什么是事务隔离,隔离级别又是什么呢? MySQL 事务 本文所说的 MySQL 事务都是指在 InnoDB 引 ...
- 【数据库】MySQL事务并发、MVCC原理及实现
文章目录 ACID 隔离性分为四个级别 数据库事务并发可能出现的问题 读已提交等级下解决脏读办法 可重复读解决不可重复读 MySQL 是如何解决幻读的 快照读和当前读 那什么又是悲观锁呢 MySQL ...
- MySQL 事务特性以及事务隔离级别
事务的概念 数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成. 事务特性(ACID) 事务拥有四个重要的特性: 原子性(Atomicity) 事务开始后 ...
- mysql事务特性及四种隔离级别
事务的特性:ACID 我刚才提到了事务的特性:要么完全执行,要么都不执行.不过要对事务进行更深一步的理解,还要从事务的 4 个特性说起,这 4 个特性用英文字母来表达就是 ACID. A,也就是原子性 ...
- MySQL事务隔离级别的实现原理
回顾 在MySQL的众多存储引擎中,只有InnoDB支持事务,所有这里说的事务隔离级别指的是InnoDB下的事务隔离级别. 读未提交:一个事务可以读取到另一个事务未提交的修改.这会带来脏读.幻读.不可 ...
- MySQL事务特性和隔离级别(脏读、不可重复读、幻读)
事务的ACID(acid)属性 1.原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不 发生. 2.一致性(Consisten ...
- mysql事务特性的主要作用是_mysql事务四大特性
本篇讲诉数据库中事务的四大特性(ACID)和简单操作 ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务 ...
最新文章
- 科技论文新在哪里?-如何写好科技论文之我见(三)
- python获取原图GPS位置信息,轻松得到你的活动轨迹
- 文章目录 | .NET Core on K8s学习之旅 (更新至20200618)
- wordpress functions.php 在哪,在functions.php中定义变量并在WordPress中的函数钩子中访问它们...
- springcloud服务注册中心eureka搭建
- WordPress基础教学:绝对必装的JetPack外挂
- 这种简历咋找工作?(运营)
- 初识Memcache之安装与测试
- sql 保留整数_Spark 3.0发布啦,改进SQL,弃Python 2,更好的兼容ANSI SQL,性能大幅提升...
- SQL Server数据库简繁体数据混用的问题
- 前端实现给页面中的某一部分生成水印
- 从QQtabBar看css命名规范BEM
- android系统与苹果手机号码,苹果手机号码怎么导入另一个手机安卓(全程图解其操作流程)...
- 什么是云渲染?为什么要用电脑渲图?
- linux拷贝文件断电后丢失,linux突然断电重启,配置文件丢失/程序无法打开/文件损坏...
- 软件产品的税收优惠政策
- JavaBeans分类
- GoLang-4(switch)
- SWUSTOJ #971 统计利用先序遍历创建的二叉树的深度
- 新能源与自动驾驶汽车市场