MySQL 事务的ACID特性

news2025/1/19 14:16:58

MySQL事务是什么,它就是一组数据库的操作,是访问数据库的程序单元,事务中可能包含一个或者多个 SQL 语句。这些SQL 语句要么都执行、要么都不执行。我们知道,在MySQL 中,有不同的存储引擎,有的存储引擎比如MyISAM 是不支持事务的,所以说MySQL 事务实际上是发生在 存储引擎部分

事务主要有四大特性,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和 持久性(Durability)。它实际上是从四个方面来阐述MySQL 事务的特点,下面就分别来看MySQL 通过什么方式来实现这些特性。

一、原子性

1. 原子性定义

原子性就是指事务的不可分割性,对于一个事务而言,就是要么都执行,要么都不执行。在MySQL 中是通过回滚来实现,比如事务中的一个 SQL 语句失败了,那么该事务的所有SQL 语句必须都进行回滚,退回到事务前的状态。

2. InnoDB 中原子性的实现

上面说到,MySQL 中原子性是通过回滚的方式来实现,那么回滚是怎么实现的?这就涉及到MySQL 中的Undo 日志,原子性就是通过 Undo log 来实现的。

具体是Undo log 会在一个事务中,记录当前 SQL 语句的上一个语句成功的执行状态,如果在执行当前 SQL 语句失败后,就可以通过 Undo log 来回滚到 SQL 语句执行前的状态,这样就能保证事务的原子操作。举个例子,比如插入一条记录:insert into test values(1,'刘备','蜀')实际上得到的记录图如下,中间的 roll_pointer 是指向undo log的指针。

undo log 在事务提交后,undo log 日志也就会被回收。

二、持久性

1.持久性定义

持久性是指事务一旦提交,它对事务的改变是永久性的,哪怕系统发生了故障,也不会改变其提交的结果。持久性是通过 Redo log 来实现的。

2.InnoDB 中持久性的实现

在讲持久性之前,先介绍一下MySQL 中 Buffer pool,我们知道MySQL 数据是存储在磁盘中,为了实现快速读写数据,我们会在内存中设置一个 Buffer pool 缓冲池,数据库可以直接与 Buffer Pool 进行读取交互,定期再将 Buffer Pool 数据存储到磁盘中,这样会大大提高数据库的读写效率。

但是如果系统断电或者宕机,内存是无法保存信息的,而此时刚好Buffer Pool 数据没有同步到磁盘上,就会造成数据丢失。因此就需要 redo log 来对更新和修改操作进行记录,使得在系统重启时能够恢复到原来的状态。

Redo log 是一种预写式日志(write-Ahead Log),它记录的是在某个数据页上做了什么修改。当有记录需要更新时,InnoDB 引擎会先把记录写到 redo log 中,在系统空闲时,再将操作记录更新到磁盘中。redo log 结构如下图所示:

  • write pos 是当前记录的位置
  • checkpoint 当前要擦除的位置
  • write pos 和 check point 之间是 redo 内存区域中还空着的部分,用于记录新的操作。

redo log 只需要记录真正修改的部分,它的同步效率要比 buffer 同步数据快的多。那么 redo log 何时会同步到磁盘中去,主要是 innodb_flush_log_at_trx_commit这个参数的设置:

  • 0:表示当提交事务时,并不将缓冲区的 redo log 写入磁盘的日志文件,而是等待主线程每秒刷新
  • 1:在事务提交时将缓冲区的 redo log 同步写到磁盘中,保证一定会写入成功
  • 2:在事务提交时将缓冲区的redo 日志异步写入到磁盘中,即不能完全保证 commit 时肯定会写入到 redo 日志文件,只是有这个动作。

建议这个参数设置为1 ,同步写入磁盘中。

3.Binlog 和 Redo log

binlog 和 redo log 日志的区别

我们知道 redo log 是InnoDB 存储引擎的事务日志,那么对于 server 层是否也存在事务日志,答案是确定的,server 层的事务日志就是 binlog (归档日志)。为啥会出现两种事务日志,是因为最开始的 MySQL 中并没有 InnoDB 引擎,MySQL 自带的引擎是 MyISAM ,用的就是 binlog 日志来实现事务。那么两者具体有什么区别呢:

  • redo log 是InnoDB 引擎特有的,binlog 是 server 层实现,所有的存储引擎都可以使用
  • redo log 是物理日志,它存储的是在数据页上的修改;binlog 是逻辑日志,存储的是sql 语句的原始逻辑
  • redo log 空间是固定的,会使用完并覆盖原来的日志。binlog 可以追加写入,不会覆盖原来的日志
binlog 和 redo log 日志的两阶段提交

既然在MySQL 中存在两种日志,那么为了让两份日志之间的逻辑一致,就需要两阶段提交来实现这一任务。具体怎么实现的,我们以这个语句update T set c=c+1 where ID = 2来看:

  • 1.执行器先通过执行引擎查找 ID=2 这一行,如果数据在内存Buffer Pool 中直接返回。如果在磁盘中,则先从磁盘中读取到内存中,然后再返回。
  • 2.对取到的数据进行操作,将值加1后得到新的数据,再调用引擎写入数据,更新内存。
  • 3.同时将对数据页的修改记录到 redo log 中,这个时候 redo log 处于第一个阶段 prepare。
  • 4.执行器生成对于这个操作的 binlog ,并将 binlog 写入磁盘中
  • 5.执行器调用提交事务接口,把刚刚写入的 redo log 修改成 commit 状态,更新到此完成。

三、隔离性

1.隔离性定义

隔离性是指事务内部的操作与其他事务是隔离的,并发过程中的各个事务之间不能互相干扰。对于事务的操作,主要分成两种:读操作与写操作之间的影响、写操作与写操作之间的影响。

2.隔离性的实现

上面我们说到了事务之间的影响主要分成两个方面,那么MySQL 中是如何处理这两种情况的呢?

  • 写操作与写操作:就像 java 中的锁一样,通过锁来解决(MySQL 锁后续会出一篇文章详细介绍)
    • 幻读
  • 写操作与读操作:主要是通过 MVCC 机制来解决(MVCC 后续会出一篇文章进行介绍)
    • 脏读
    • 不可重复读
写操作与写操作的隔离实现

我们可以通过锁的方式,来保证同一时刻的一个数据的写操作只能被一个事务所执行。

在MySQL 中,根据加锁范围,大致可以分成三类:全局锁、表级锁和行级锁。 在一个事务修改数据前,需要获取对应的锁才能修改对应的数据。其他事务想要修改该数据,必须要等到之前的事务提交或回滚释放锁后,才能抢这个锁来修改数据。

锁的概况可以通过以下语句进行查询:

# 锁的概况
select * from information_schema.innodb_locks;
# InnoDB 整体状态,也包括锁的情况
show engine innodb status
写操作与读操作的隔离实现

为了保证性能,我们不能把所有操作都进行上锁,对于写操作和读操作,可以使用不加锁的方式来实现事务隔离。主要就是通过MySQL 中的 MVCC 机制来解决。

四、一致性

一致性的定义与实现

一致性的实现就是在前面三个特性实现的基础上而来的,没有前面三个特性的实现,也就达不到最后数据库事务的一致性。

参考资料

https://time.geekbang.org/column/article/68963

https://www.cnblogs.com/kismetv/p/10331633.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1331026.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

省时攻略:快速获得Creo安装包,释放创意天才!

不要再在网上浪费时间寻找Creo的安装包了,一键下载安装, 你要的一切都可以在这里找到!我们深知在海量的信息中寻找合适的软件包并非易事,而且往往还伴随着繁琐的安装过程。然而,现在有了我们,一切变得轻松简…

【飞凌 OK113i-C 全志T113-i开发板】一些有用的常用的命令测试

一些有用的常用的命令测试 一、系统信息查询 可以查询板子的内核信息、CPU处理器信息、环境变量等 二、CPU频率 从上面的系统信息查询到,这是一颗具有两个ARMv7结构A7内核的处理器,主频最高1.2GHz 可以通过命令查看当前支持的频率以及目前所使用主频 …

爬虫工作量由小到大的思维转变---<第二十三章 Scrapy开始很快,越来越慢(医病篇)>

诊断篇https://blog.csdn.net/m0_56758840/article/details/135170994?ops_request_misc%257B%2522request%255Fid%2522%253A%2522170333243316800180644102%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id1703332433168001806441…

更改WiseAlign软件界面图标方法

更改WiseAlign软件界面图标方法 未替换时 首先将图片转换为BMP格式,在搜索栏处输入画图,点击打开画图工具 按住图标拖动到画布内,或是直接CtrlV将图标复制到画布内 点击文件,再点击另存为 保存类型选择“24位位图(*.bm…

SpringBoot3-基础特性

文章目录 自定义 banner自定义 SpringApplicationFluentBuilder APIProfiles指定环境环境激活环境包含Profile 分组Profile 配置文件 外部化配置配置优先级 外部配置导入配置属性占位符 单元测试-JUnit5测试组件测试注解断言嵌套测试参数化测试 自定义 banner banner 就是启动…

MySQL数据库 触发器

目录 触发器概述 语法 案例 触发器概述 触发器是与表有关的数据库对象,指在insert/update/delete之前(BEFORE)或之后(AFTER),触发并执行触发器中定义的soL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性,日志记录&am…

idea多光标无法取消

通常按住alt 鼠标左键。是多光标操作 但是不知道怎么按照了导致一直多光标 使用 altshiftinsert 取消多光标

【优质书籍推荐】LoRA微调的技巧和方法

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…

【Unity基础】9.地形系统Terrain

【Unity基础】9.地形系统Terrain 大家好,我是Lampard~~ 欢迎来到Unity基础系列博客,所学知识来自B站阿发老师~感谢 (一)地形编辑器Terrain (1)创建地形 游戏场景中大多数的山川河流地表地貌都是基…

vue微乾坤子应用开发及ele组件开发时问题记录

一. 微乾坤 1. 新增page页面路由,pmi权限中心配置正常,跳转链接正确,但路由未找到403. 解决: 新增的配置是page类型,transformQianKunRoute方法转换微前端路由数据 时,过滤未兼容page型的路由, 解决 [menu,…

Git的总体认知与具体实现

GIt概念 是一种分布式控制管理器 tips:敏捷开发 -> 先上线,后续开发再继续开发 集中式和分布式 集中式的版本控制系统每次在写代码时都需要从服务器中拉取一份下来,并且如果服务器丢失了,那么所有的就都丢失了,你本机客户端仅…

神经网络:深度学习基础

1.反向传播算法(BP)的概念及简单推导 反向传播(Backpropagation,BP)算法是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见算法。BP算法对网络中所有权重计算…

MySQL代码笔记

欢迎来到Cefler的博客😁 🕌博客主页:那个传说中的man的主页 🏠个人专栏:题目解析 🌎推荐文章:题目大解析(3) 目录 👉🏻表的增删查改创建表格&…

word2003 open word2007+

Win 7 C:\Documents and Settings\Administrator\Application Data\Microsoft\Templates 还是不行,重装office2003吧,再安装转换插件,但是再高版本好像没转换工具

Python+Playwright自动化测试--playwright处理浏览器多窗口切换

1.简介 浏览器多窗口的切换问题相比大家不会陌生吧,之前小编在javaselenium系列文章中就有介绍过。大致步骤就是:使用selenium进行浏览器的多个窗口切换测试,如果我们打开了多个网页,进行网页切换时,我们需要先获取各…

使用Java语言解决古典猴子分桃问题

一、主要思想 五只猴子分桃 第一只猴子呀 平均分成五分 挤出来多一个 多的扔入海中 拿了其中一份 来了五只猴子 均是如此操作 第五只猴子呀 还存有多少只 二、基本代码 public class MonkeyPeach {public static void main(String[] args){int n 1;int m 0;int flag1;int…

MyBatis的延迟加载!!!

首先:MyBatis的关联查询!!!(一对一、一对多、多对多)-CSDN博客以这个项目为基础。 1.在UserMapper接口中创建一个方法: package com.by.mapper;import com.by.pojo.User;import java.util.Lis…

GDAL3.7编译一:普通压缩类算法库编译(zlib/zstd/lz4/liblzma/brotli)

通过整理gdal所有依赖库,发现压缩类的三方库被依赖的频率很高,而且这些三方库又不依赖别的库,因此首先编译。 1.zlib库编译: 源码下载地址:GitHub - madler/zlib: A massively spiffy yet delicately unobtrusive co…

电力系统风储联合一次调频MATLAB仿真模型

微❤关注“电气仔推送”获得资料(专享优惠) 简介: 同一电力系统在不同风电渗透率下遭受同一负荷扰动时,其频率变化规律所示: (1)随着电力系统中风电渗透率的不断提高,风电零惯性响…

HTML5+CSS3+Vue小实例:彩带圣诞树

实例:彩带圣诞树 技术栈:HTML+CSS+Vue 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><…