阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?

尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,很多小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试机会,遇到很多很重要的面试题:

事务ACID,底层是如何实现的?

ACID靠什么保证的?

ACID的一致性是指什么?是如何实现的?

ACID中的持久性是指什么?是如何实现的?

ACID中的隔离性是指什么?是如何实现的?

最近有小伙伴在面试阿里,又遇到了MVCC相关的面试题。小伙伴 支支吾吾的说了几句,没说清楚,面试挂了。

所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。

这里,尼恩团队把MVCC/ 事务 进行了全面的梳理,穿透式的梳理,

梳理为一个PDF文档 《MVCC 学习圣经:一次穿透MYSQL MVCC 》, 并且持续迭代。

这个文档将成为大家 面试的杀手锏, 此文当最新PDF版本,可以找40岁老架构师尼恩获取。

在这里插入图片描述

当然,上面的面试题以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V171版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,回复:领电子书

本文作者:

  • 第一作者 Moen (负责写初稿 )
  • 第二作者 尼恩 (40岁老架构师, 负责提升此文的 技术高度,让大家有一种 俯视 技术的感觉)

什么是事务

事务(Transaction)是数据库管理系统执行过程中的一个逻辑单位,它由一个有限的数据库操作序列构成。

事务(Transaction)是访问和更新数据库的程序执行单元;

事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。

这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。

事务的目的是确保数据的完整性和一致性,它通过一系列的操作,将数据库从一个一致性状态转换到另一个一致性状态。

首先回顾一下MySQL事务的基础知识。

MySQL逻辑架构和存储引擎

在这里插入图片描述

如上图所示,MySQL服务器逻辑架构从上往下可以分为三层:

(1)第一层:处理客户端连接、授权认证等。

(2)第二层:服务器层,负责查询语句的解析、优化、缓存以及内置函数的实现、存储过程等。

(3)第三层:存储引擎,负责MySQL中数据的存储和提取。

MySQL 中服务器层不管理事务,事务是由存储引擎实现的。

MySQL支持事务的存储引擎有InnoDB、NDB Cluster等,其中InnoDB的使用最为广泛;其他存储引擎不支持事务,如MyIsam、Memory等。

如无特殊说明,后文中描述的内容都是基于InnoDB。

innodb 一个数据库事务( transaction)的执行过程

数据库事务( transaction) 是指作为一个逻辑工作单元执行的一系列数据库操作,这些操作要么全部成功,要么全部失败,是一个不可分割的工作单元。

事务是在事务开始和事务结束之间执行的一系列数据库操作。

事务的目的是确保数据库操作的一致性和完整性,同时提供对并发访问的隔离性和恢复能力。

图解:一个简化版的执行过程

下面是一个简化版的执行过程

图片

注意:请点击图像以查看清晰的视图!

图解:一个详细版的一个数据库事务( transaction)的执行过程

下面是一个详细版的一个数据库事务( transaction)的执行过程

在这里插入图片描述

注意:请点击图像以查看清晰的视图!

InnoDB的一次更新事务涉及到多个组件和步骤,包括Buffer Pool、BinLog、UndoLog、RedoLog以及物理磁盘。

下面是一次完整的事务更新操作过程:

step1. 开始数据,InnoDB 收到更新请求

执行SQL,收到事务的更新请求

step2. 加载数据到缓存中(Buffer Pool)

在进行数据更新时,InnoDB首先在缓冲池(Buffer Pool)中查找待更新记录是否已经在内存中。若记录不在内存中,InnoDB会将记录从磁盘文件读取到缓冲池(Buffer Pool)中。

缓冲池是InnoDB存储引擎提供的临时存储区,用于提升数据读取和修改的速度。将数据加载到缓冲池后,后续的更新操作均在缓冲池内进行。这样可以减少磁盘I/O操作,从而提高事务处理速度。缓冲池在内存中存储数据,可以降低磁盘I/O的开销,提高数据读取和写入的速度,从而优化事务处理性能。

step3. 写入Undo Log

在更新数据之前,InnoDB会将原始数据的副本写入Undo Log(回滚日志)。

Undo Log是保证事务回滚和并发控制的关键部分,也是确保事务原子性和一致性的重要机制。Undo Log记录了事务开始前的数据状态,以便在需要回滚时进行数据恢复。通过记录撤销日志,InnoDB能够实现事务的滚动回滚,提高事务处理的灵活性。撤销日志在事务处理过程中起到了关键作用,它记录了事务的修改过程,使得事务能够在需要时回滚到之前的状态,保证数据的一致性和完整性。

step4. 更新内存数据,包括 Buffer Pool和 Redo Log Buffer

接下来,InnoDB会在缓冲池中更新数据。

这意味着,当执行update语句时,InnoDB会先更新已经读取到Buffer Pool中的数据,修改操作会直接在内存中进行,而不是立即写入磁盘。

此时,缓冲池中的数据被标记为"脏页",表示与磁盘上的数据不一致。脏页是缓冲池中已经被修改但尚未写入磁盘的数据页,它需要后续的处理才能将修改同步到磁盘,保证数据的持久性。

更新Buffer Pool和Redo Log Buffer通常是数据库系统内部的操作,这些操作可以作为事务处理的一部分。

更新Buffer Pool和Redo Log Buffer的一般步骤:

第一步:Buffer Pool更新:
缓冲池 (Buffer Pool) 是数据库系统中用于存储数据页的内存区域。当需要读取或写入数据时,数据库系统首先会检查缓冲池,如果数据页已经在缓冲池中,就可以直接进行访问,而不必去访问磁盘。
要更新Buffer Pool,首先需要确定要读取或写入的数据页。如果数据页已经在缓冲池中,可以直接进行读取或写入操作;如果数据页不在缓冲池中,则需要将其从磁盘加载到缓冲池中。
更新Buffer Pool的过程通常是由数据库系统自动管理的,但也可以通过合适的API或查询语句手动进行。

第二步:Redo Log Buffer更新:
重做日志(Redo Log)是数据库系统用于持久化事务操作的一种技术。

当事务进行数据更新时,数据库系统会首先将更新操作记录到Redo Log中,以确保即使在系统崩溃时也能够恢复到事务之前的状态。
Redo Log Buffer是一个内存区域,用于暂时存储事务更新操作的日志记录。在事务进行数据更新时,数据库系统会将更新操作记录到Redo Log Buffer中,然后定期将其写入到磁盘的Redo Log文件中。
更新Redo Log Buffer通常是在事务进行提交(Commit)时完成的。

当事务提交时,数据库系统会确保将Redo Log Buffer中的所有日志记录写入到磁盘中,以保证事务的持久性。

在更新Buffer Pool和Redo Log Buffer时,数据库系统通常会采取一些优化措施,例如异步写入、批量提交等,以提高性能和减少IO开销。同时,数据库管理员也可以通过调整参数和配置来优化Buffer Pool和Redo Log Buffer的性能。

step5 写入Redo Log 文件

为了保证事务的持久性,InnoDB在Buffer Pool中记录修改操作的同时,InnoDB会先将更新操作写入Redo Log(重做日志)。

Redo Log是一种物理日志,它记录了事务对数据库的修改操作。

通过Redo Log,即使系统发生故障,也可以通过重做日志来恢复事务修改后的状态。

这一机制保证了事务的可靠性,降低了系统故障带来的风险。

重做日志是保证数据持久性和恢复性的关键,它记录了事务的修改过程,使得事务的修改能够在故障恢复后得到恢复。

step6. 提交事务

当事务完成所有的更新操作后,事务被提交。

在提交事务时,InnoDB会将事务标记为"准备提交"状态。

此时,事务的修改操作仍然在缓冲池中,尚未写入磁盘。

事务提交是事务处理的重要环节,它标志着事务处理完毕,可以进行后续的提交操作。

在提交之前,事务的修改操作需要得到处理,保证数据的完整性和一致性。

step7. 写入BinLog

在事务提交之后,InnoDB会将事务的修改操作写入BinLog(归档日志)。

BinLog是MySQL的二进制日志,用于记录数据库的所有修改操作。

在归档日志中记录的信息包括:事务开始的时间、数据库名、表名、事务ID、SQL语句等。

它可以用于数据恢复、主从复制、数据分析和同步等场景。

归档日志在数据库中起到了关键作用,它记录了数据库的修改过程,使得数据库的修改能够在故障恢复后得到恢复。

step8. 刷新脏页到磁盘

最后,在提交过程完成后,InnoDB会将缓冲池(Buffer Pool)中的脏页刷新到物理磁盘上的数据文件中。

这个过程称为"刷脏"。

通过刷脏操作,将缓冲池中的修改操作同步到磁盘,确保数据的持久性。

然而,这个写入过程并非立即执行,而是由后台线程异步执行的,因此可能会有一定的延迟。

总而言之,MySQL会在适当的时机选择将数据写入磁盘以进行持久化。

典型的MySQL事务

典型的 MySQL 事务通常包括以下步骤:

  1. 开始事务:使用 START TRANSACTIONBEGIN 命令来开始一个新的事务。这将确保接下来的操作将被视为一个事务单元,并且要么全部成功提交,要么全部失败回滚。
  2. 执行SQL操作:在事务中执行各种SQL操作,例如插入、更新或删除数据,查询等。这些操作可能会涉及一个或多个数据库表。
  3. 数据处理与验证:在执行SQL操作之前或之后,进行数据处理和验证。这可能包括检查约束条件、验证输入数据的有效性等。
  4. 提交或回滚事务:如果所有的数据库操作都成功,并且通过了数据验证步骤,那么事务可以被提交(COMMIT)。这将导致所有的更改永久地应用到数据库中。如果在任何时候出现了错误或者违反了事务的约束条件,那么整个事务将会被回滚(ROLLBACK),所有的更新将被撤销,数据库将恢复到事务开始之前的状态。
  5. 结束事务:一旦事务被提交或者回滚,事务就结束了。可以使用 COMMITROLLBACK 命令来结束事务。此时数据库会释放任何由事务占用的资源。

以下是一个典型的MySQL事务的示例:

START TRANSACTION;

-- 执行SQL操作
INSERT INTO orders (customer_id, total_amount) VALUES (123, 100);
UPDATE customers SET points = points + 10 WHERE id = 123;

-- 数据处理与验证
IF (SELECT total_amount FROM orders WHERE id = LAST_INSERT_ID()) > 50 THEN
    COMMIT;
ELSE
    ROLLBACK;
END IF;

-- 提交或回滚事务
COMMIT;

在这个示例中,事务首先通过 START TRANSACTION 开始,然后执行一系列SQL操作,包括向 orders 表中插入一条新的订单记录和更新 customers 表中客户的积分。接着进行了数据处理和验证,如果订单的总金额大于50,则提交事务,否则回滚事务。最后使用 COMMIT 命令提交事务。

典型的MySQL事务是如下操作的:

START TRANSACTION;

-- 执行SQL操作

-- 提交
COMMIT;

其中start transaction标识事务开始,commit提交事务,将执行结果写入到数据库。

如果sql语句执行出现问题,会调用rollback,回滚所有已经执行成功的sql语句。

START TRANSACTION;

-- 执行SQL操作

-- 回滚
ROLLBACK;

当然,也可以在事务中直接使用rollback语句进行回滚。

MySQL自动提交

在 MySQL 中,默认情况下是开启了自动提交(Auto-Commit)模式的。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值