数据库ACID四大特性到底为了啥,一文带你看通透

article/2025/9/29 20:53:26

小伙伴想精准查找自己想看的MySQL文章?喏 → MySQL江湖路 | 专栏目录

  说起数据库四大特性,同学们张口就来,ACID!那为什么要ACID?每种特性的原理又是什么?如何实现的?废话少说,哈哥今天带你搞清楚,快上车!
  ACID,是用来声明数据库事务的四大特性,即原子性 (Atomicity)、 一致性(Consistency)、隔离性(Isolation) 和 持久性(Durability)

在这里插入图片描述

目录

  • 谈谈个人理解
  • 一、ACID特性
  • 二、ACID具体实现
    • 1、原子性原理
    • 2、持久性原理
    • 3、隔离性原理
    • 4、一致性原理
  • 总结

谈谈个人理解

  简单说,事务就是一组原子性的SQL执行单元。如果数据库引擎能够成功地对数据库应 用该组査询的全部语句,那么就执行该组SQL。如果其中有任何一条语句因为崩溃或其 他原因无法执行,那么所有的语句都不会执行。要么全部执行成功(commit),要么全部执行失败(rollback)

  这里引用银行转账的例子,假设银行的数据库有两张表:信用卡(credit)表和储蓄(savings)表。用户陈哈哈要把信用卡里最后100块钱额度转到他 的储蓄账户用来吃饭,那么需要至少三个步骤:

  1. 检査信用卡余额是否髙于100块钱。
  2. 从信用卡账户余额中减去100块钱。
  3. 在储蓄账户余额中增加100块钱。

  上述三个步骤必须在同一个事务中执行,任何一个SQL失败,则必须回滚所有的SQL。这里用START TRANSACTION语句开启事务,要么使用COMMIT提交事务将修改的数据持久保留,要么使用ROLLBACK销所有的修改。事务SQL的样本如下:

START TRANSACTION;
-- 检查信用卡账户额度
SELECT balance FROM credit WHERE customer_id = 'chenhh';
-- 信用卡表扣钱
UPDATE credit SET balance = balance - 100.00 WHERE customer_id = 'chenhh';
-- 储蓄表加钱
UPDATE savings SET balance = balance + 100.00 WHERE customer_id = 'chenhh';
COMMIT;

  试想一下,如果执行到第四条语句时服务器崩溃了,会发生什么?废话,我被坑了100块钱,中午只能饿肚子!再假如,在执行到第三条语句和第四 条语句之间时,同一时间,另外一个进程,来自商场结账的女朋友,也要信用卡账户的100块,那么结果可能就是银行在不知道这个逻辑的情况下白白给了陈哈哈女朋友100块钱?

在这里插入图片描述

  别做梦了,主流关系型数据库(如MySQL、Oracle等)是通过了严格的ACID测试,不会随便出这种BUG的。那么我们今天就一起来搞懂ACID的核心原理。

一、ACID特性

  • 原子性(Atomicity)

  单个事务,为一个不可分割的最小工作单元,整个事务中的所有操作要么全部commit成功,要么全部失败rollback,对于一个事务来说,不可能只执行其中的一部分SQL操作,这就是事务的原子性。

  • 一致性(Consistency)

  数据库总是从一个一致性的状态转换到另外一个一致性的状态。在前面的例子中, 一致性确保了,即使在执行第三、四条语句之间时系统崩潰,信用卡账户也不会损 失100块,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中,保证数据一致性。

  • 隔离性(Isolation)

  通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。在前面 的例子中,当执行完第三条语句、第四条语句还未开始时,此时有另外一个账户查询余额SQL开始运行,则其看到的信用卡账户的余额并没有被减去100元。后面我们讨论隔离级别(Isolation level)的时候,会发现为什么我们要说事务通常来说是不可见的

  • 持久性(Durability)

  一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。

  事务的ACID特性可以确保银行不会弄丢你的钱。而在应用逻辑中,要实现这一点非常难, 甚至可以说是不可能完成的任务。一个兼容ACID的数据库系统,需要做很多复杂但可能用户并没有觉察到的工作,才能确保ACID的实现。

二、ACID具体实现

  对MySQL来说,逻辑备份日志(binlog)、重做日志(redolog)、回滚日志(undolog)、锁技术 + MVCC就是MySQL实现事务的基础

  • 原子性:通过undolog来实现。
  • 持久性:通过binlog、redolog来实现。
  • 隔离性:通过(读写锁+MVCC)来实现。
  • 一致性:MySQL通过原子性,持久性,隔离性最终实现(或者说定义)数据一致性。

学习MySQL日志可参考《听我讲完redo log、binlog原理,面试官老脸一红》
学习MySQL锁机制可参考 《面试让HR都能听懂的MySQL锁机制,欢声笑语中搞懂MySQL锁》

1、原子性原理

事务通常是以BEGIN TRANSACTION 开始,以 COMMIT 或 ROLLBACK 结束。

  • COMMIT 表示提交,即提交事务的所有操作并持久化到数据库中。
  • ROLLBACK表示回滚,即在事务中运行的过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库所有已完成的操作全部撤销,回滚到事务开始时的状态,这里的操作指对数据库的更新操作,已执行的查询操作不用管。这时候也就需要用到 undolog 来进行回滚。

undolog:

  1. 每条数据变更(INSERT/UPDATE/DELETE/REPLACE)等操作都会生成一条undolog记录,在SQL执行前先于数据持久化到磁盘。
  2. 当事务需要回滚时,MySQL会根据回滚日志对事务中已执行的SQL做逆向操作,比如 DELETE 掉一行数据的逆向操作就是再把这行数据 INSERT回去,其他操作同理。

2、持久性原理

  先了解一下MySQL的数据存储机制,MySQL的表数据是存放在磁盘上的,因此想要存取的时候都要经历磁盘 IO,然而即使是使用 SSD 磁盘 IO 也是非常消耗性能的。为此,为了提升性能 InnoDB 提供了缓冲池(Buffer Pool),Buffer Pool 中包含了磁盘数据页的映射,可以当做缓存来使用:

  • 读数据:会首先从缓冲池中读取,如果缓冲池中没有,则从磁盘读取在放入缓冲池;
  • 写数据:会首先写入缓冲池,缓冲池中的数据会定期同步到磁盘中;

  我们知道,MySQL表数据是持久化到磁盘中的,但如果所有操作都去操作磁盘,等并发上来了,那处理速度谁都吃不消,因此引入了缓冲池(Buffer Pool)的概念,Buffer Pool 中包含了磁盘中部分数据页的映射,可以当做缓存来用;这样当修改表数据时,我们把操作记录先写到Buffer Pool中,并标记事务已完成,等MySQL空闲时,再把更新操作持久化到磁盘里(你可能会问,到底什么时候执行持久化呢?1、MySQL线程低于高水位;2、当有其他查询、更新语句操作该数据页时),从而大大缓解了MySQL并发压力。

  但是它也带来了新的问题,当MySQL系统宕机,断电时Buffer Pool数据不就丢了?

  因为我们的数据已经提交了,但此时是在缓冲池里头,还没来得及在磁盘持久化,所以我们急需一种机制需要存一下已提交事务的数据,为恢复数据使用。

  于是 redo log + binlog的经典组合就登场了,这里不在扩展赘述。可参考《听我讲完redo log、binlog原理,面试官老脸一红》

3、隔离性原理

  隔离性是事务ACID特性里最复杂的一个。在SQL标准里定义了四种隔离级别,每一种级别都规定一个事务中的修改,哪些是事务之间可见的,哪些是不可见的。

  级别越低的隔离级别可以执行越高的并发,但同时实现复杂度以及开销也越大。

搞懂MySQL事务隔离级别请参考《上个厕所的功夫,搞懂MySQL事务隔离级别》

Mysql 隔离级别有以下四种(级别由低到高):

隔离级别效果
读未提交(RU)一个事务还没提交时,它做的变更就能被别的事务看到。(别的事务指同一时间进行的增删改查操作)
读提交(RC)一个事务提交(commit)之后,它做的变更才会被其他事务看到。
可重复读(RR)一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。
当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。
串行(xíng)化(S)正如物理书上写的,串行是单线路,顾名思义在MySQL中同一时刻只允许单个事务执行,“写”会加“写锁”,“读”会加“读锁”。
当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

  搞懂了隔离级别以及实现原理其实就可以理解ACID里的隔离性了。前面说过原子性,隔离性,持久性的目的都是为了要做到一致性,但隔离型跟其他两个有所区别,原子性和持久性是为了要实现数据的正确、可用,比如要做到宕机后的恢复、事务的回滚等,保证数据是正确可用的!

  那么隔离性是要做到什么呢?

  隔离性要管理的是:多个并发读写请求(事务)过来时的执行顺序。像交警在马路口儿指挥交通一样,当并发处理多个DML更新操作时,如何让事务操作他该看到的数据,出现多个事务处理同一条数据时,让事务该排队的排队,别插队捣乱,保证数据和事务的相对隔离,这就是隔离性要干的事儿。
在这里插入图片描述

  一段大白话,听的明明白白的同学们,记得收藏转发一波,或许,你能帮到别人!

  所以,从隔离性的实现原理上,我们可以看出这是一场数据的可靠性与性能之间的权衡。

4、一致性原理

  一致性,我们要保障的是数据一致性,数据库中的增删改操作,使数据库不断从一个一致性的状态转移到另一个一致性的状态

  事务该回滚的回滚,该提交的提交,提交后该持久化磁盘的持久化磁盘,该写缓冲池的写缓冲池+写日志;对于数据可见性,通过四种隔离级别进行控制,使得库表中的有效数据范围可控,保证业务数据的正确性的前提下,进而提高并发程度,支撑服务高QPS的稳定运行,保证数据的一致性,这就是咱们叨叨叨说的清楚想不明白的数据库ACID四大特性。

总结

  希望通过本篇文章你熟知并搞懂了我们天天说的数据库ACID四大特性,本文中我们一起串联了起来,相信你不会在忘记某一个,打麻将三缺一怎么行?

  好了,多了就不说了,我劝你耗子尾汁,但推荐你关注我,因为我会让你在快乐中学会很多东西!


MySQL系列文章汇总与《MySQL江湖路 | 专栏目录》

往期热门MySQL系列文章

  • 原创 | MySQL中特别实用的几种SQL语句送给大家
  • 原创 | SQL优化最干货总结 - MySQL(2020最新版)
  • 原创 | 为什么大家都说SELECT * 效率低
  • 原创 | 面试让HR都能听懂的MySQL锁机制,欢声笑语中搞懂MySQL锁
  • 原创 | MySQL中的 utf8 并不是真正的UTF-8编码 ! !
  • 原创 | MySQL数据中有很多换行符和回车符!!该咋办?
  • 原创 | delete后加 limit是个好习惯么
  • 原创 | MySQL慢查询,一口从天而降的锅!

http://chatgpt.dhexx.cn/article/7N4YQAYT.shtml

相关文章

ACID是靠什么来保证的?

首先,什么是ACID? 原子性(A): 原子性就是一个事务内的操作,要么全部成功,要么全部失败。一致性(C) 一致性就是一个正确的结果到另一个正确的结果。换句话说就是一个事…

mysql的ACID

ACID是衡量事务的四个特性: 原子性(Atomicity,或称不可分割性)一致性(Consistency)隔离性(Isolation)持久性(Durability) 原子性:语句要么全执行&…

ACID

细节其实很多。。。 1 到底什么是ACID 首先需要说明的是,在IT领域,很多名词在不同的上下文环境中的语义是不同的。例如某些产品宣称支持“100% ACID”和“强一致性”等。那么,这些名词到底指的是什么?如果不结合具体的语境&#x…

[MySQL]事务ACID详解

专栏简介 :MySql数据库从入门到进阶. 题目来源:leetcode,牛客,剑指offer. 创作目标:记录学习MySql学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 1. 事务的概念 2. 事务的特性 3.事务控制语法…

数据库的ACID是什么

欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。 事务在当今的企业系统无处不在,即使在高并发环境下也可以提供数据的完整性。一个事务是一个只包含所有读/写操作成功…

谈谈数据库的ACID

谈谈数据库的ACID 帅宏军 一.事务 定义:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。 准备工作:为了说明事务的ACID原理,我们使用银行账户及资金…

数据库中的 ACID 属性

💂 个人网站:【海拥】【摸鱼游戏】【神级源码资源网】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 想寻找共同学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 大多数使用数据库的程…

什么是ACID?它的特性是什么?

https://baijiahao.baidu.com/s?id1743501877867119042&wfrspider&forpc ACID是指数据库管理系统(DBMS)在写入或更新资料的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性&…

事务ACID理解

事务管理(ACID) 谈到事务一般都是以下四点 原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 一致性(Consistency) 事务前后数据…

vue页面刷新 reload()

首先在vue里配置 在所想添加reload的vue里直接如下: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190610082256841.png?x-oss-processimage/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTAxMTkxMA…

重识Nginx - 16 Nginx reload流程浅析

文章目录 图解reload流程1.向master程发送HUP号( reload命令)2.master进程校验配置语法是否正确3.master进程打开新的监听端口4.master进程用新配置启动新的worker 进程5.master进程向老worker 进程发送QUIT号6.老worker进程关闭监听句柄,处理完当前连接后结束进程 图解reload流…

vue this.reload 方法 配置, 优于window.reload()的页面刷新

相关网址: https://www.cnblogs.com/yinn/p/9056731.html 1.场景 在处理列表时,常常有删除一条数据或者新增数据之后需要重新刷新当前页面的需求。 2.遇到的问题 1. 用vue-router重新路由到当前页面,页面是不进行刷新的 2.采用window.re…

Nginx reload

解释 /usr/local/nginx/sbin/nginx -s reload 用过多次这条命令,一直以为是重启Nginx,今天有幸看了下Nginx官方文档介绍这条命令 Nginx服务不会终止,主进程检查配置,应用配置的过程。主进程会启动一个新的工作进程处理新来的请求…

layui table.reload()

使用table.reload()重载去搜索特定列 html <div class"searchTable" id"searchTable"><div class"layui-inline"><input class"layui-input layui-inline" id"badge" placeholder"badge" autoc…

为什么 NGINX 的 reload 命令不是热加载?

这段时间在 Reddit 看到一个讨论&#xff0c;为什么 NGINX 不支持热加载&#xff1f;乍看之下很反常识&#xff0c;作为世界第一大 Web 服务器&#xff0c;不支持热加载&#xff1f;难道大家都在使用的 nginx -s reload 命令都用错了&#xff1f;带着这个疑问&#xff0c;让我们…

Unity 手动编译 Reload脚本 减少等待时间

Unity 手动编译 Reload 脚本 这是个自定义reload domain工具,加快工作流,减少等待.测试版本是Unity2021,理论上来说2020以上都可. 脚本地址:UnityManualReload (github.com) 在Unity中遇到的问题 在unity工作流中,修改脚本->编译脚本->reload domain(重载域)-> 进…

layui table reload 重载

在所有记录中通过姓名搜索需要的数据&#xff0c; 搜索记录为空时返回所有记录 HTML&#xff1a; 方法渲染table&#xff1a; 表格重载&#xff1a; reload将再次访问servlet 第一次访问&#xff1a; reload访问&#xff1a; ennn&#xff0c;然后就是后台操作了&#xff0c;我…

搬运 auto_reload preload

原文&#xff1a; STM32CubeMX配置时钟中的auto-reload precload_飞由于度的博客-CSDN博客 STM32的定时器开发基础的时候&#xff0c;产生了一个疑问&#xff0c;这里不需要使能自动重装载吗&#xff1f; 带着这个疑问我去查了一下《STM32 HAL 库开发实战指南》&#xff0c;在…

4、Nginx命令(reload很重要)

Nginx命令&#xff08;reload很重要&#xff09; ./nginx -s reload &#xff1a;当我们更改了配置文件&#xff0c;我们都要重新加载我们的配置文件也就是reload例如我们的更改端口号变80位8080 连接不上的操作

js 刷新当前页面的方法 reload() , replace()的简单使用

本文为大家介绍三种 js 刷新当前页面的方法&#xff0c;我是在vue实例下写的&#xff1a; 添加定时器是为了直观看到刷新效果&#xff08;每次刷新都会重置为0&#xff09;&#xff1b; reload() 方法; replace() 方法; 页面自动刷新; reload() 方法 reload()方法用于刷新当…