深入剖析mysql ACID实现的底层原理

原子性(Atomicity)

原子性是指在一个事务(Transaction)中的操作要么全部成功,要么全部失败。在MySQL中,这是通过以下机制实现的(其实很多博客再说是通过Undo log来实现的准确来说并不严谨):

1. 事务日志(Transaction Log)
重做日志(Redo Log): 用于确保事务的持久性。当一个事务提交前,其所做的所有修改都会先被写入重做日志。即使在事务提交后数据库立即崩溃,这些修改也可以通过重做日志恢复,这就保证了事务所有的写操作可以全部一起成功

撤销日志(Undo Log): 用于事务的回滚操作。如果一个事务需要被撤销或回滚,撤销日志记录了如何将数据库状态回退到事务开始之前的状态,这就保证了事务的所有写操作可以全部一起失败

2. 事务状态管理
MySQL管理每个事务的状态,确保它们完整地执行或完全不执行。事务的状态包括“活动”、“部分提交”、“提交”和“失败”等

3. 锁机制
锁机制防止其他事务干扰正在执行的事务。这确保了在一个事务完成之前,其它事务不能读取或修改被锁定的数据

示例:银行转账事务
假设有一个简单的银行转账场景,从账户A向账户B转账100元。在MySQL中,这个操作可以作为一个事务来处理

START TRANSACTION; 

-- 从账户A扣除100元 UPDATE accounts SET balance = balance - 100 WHERE account_id = 'A'; 

-- 给账户B增加100元UPDATE accounts SET balance = balance + 100 WHERE account_id = 'B'; 

COMMIT;

整个流程的时序图:

原子性.png

底层原理

1.启动事务

START TRANSACTION 命令初始化一个新事务,并设置其状态为“活动”

2.执行操作

  • 当执行第一个UPDATE 语句时,MySQL记录这个更改到撤销日志中,并将更改后的数据页标记为脏页(Dirty Page),同时在重做日志中记录这一操作
  • 同样,第二个UPDATE语句也会进行类似操作

3.检查点(Checkpoint)

这些更改虽在内存中完成,但尚未写入磁盘。MySQL会在特定时机(如事务提交、定时任务等)通过创建检查点将脏页写回磁盘

4.提交或回滚

  • 如果两个UPDATE操作都成功,事务达到“部分提交”状态。执行COMMIT命令后,事务状态变为“提交”,这时所有更改都会被永久保存
  • 如果任一操作失败,事务状态变为“失败”,MySQL将利用撤销日志将所有更改回滚到事务开始前的状态,确保原子性

一致性

一致性在数据库系统中指的是确保所有的数据库事务都从一个一致的状态转移到另一个一致的状态。在MySQL中,一致性不仅关注数据的正确性,也涉及维护事务间的逻辑一致性。

实现机制

1.数据完整性规则:

  • 键约束:如主键和外键,确保数据库表中的数据唯一性和引用完整性
  • 数据类型和范围约束:确保输入数据符合预定义的数据类型和范围
  • 自定义规则:比如CHECK约束(在MySQL 8.0及更高版本中),用于定义特定的数据有效性规则

2.事务隔离级别

  • Mysql提供了如READ UNCOMMITTED、READ COMMITTED、REPEATABLE
    READ和SERIALIZABLE的不同隔离级别
  • 不同级别在保护数据一致性和系统性能之间提供了不同的平衡。例如,REPEATABLE
    READ是MySQL的默认隔离级别,它通过锁和MVCC机制来防止“不可重复读取”和“幻读”

3.锁机制

  • 锁是维护一致性的一种重要机制,用于控制多个事务对同一数据的访问
  • MySQL中的InnoDB存储引擎使用行级锁和表级锁来维护数据一致性

4.多版本并发控制(MVCC)

  • MVCC是一种用于实现事务隔离的技术,允许多个事务同时访问同一数据,而不会互相干扰
  • 通过创建数据的快照版本,MVCC确保了即使在数据被并发访问时,每个事务也能看到一个一致的数据视图

5.自动回滚

当事务遇到错误(如违反数据完整性规则)或故障时,MySQL会自动回滚该事务,恢复到事务开始前的状态,从而保持数据库的一致性

隔离性

隔离性是数据库事务处理的关键特性之一,它确保并发执行的事务彼此独立,互不干扰

实现机制:
MySQL通过实现不同的事务隔离级别,结合有效的锁机制和MVCC,保证了事务的隔离性,在一致性中有介绍,这里就不在赘述

持久性

持久性是数据库事务的一个关键特性,它确保一旦事务被提交,所做的更改就是永久性的,即使发生系统崩溃或电源故障。在MySQL中,持久性主要通过日志系统和数据写入策略来实现。

实现机制

1.重做日志(Redo Log):

  • MySQL中的InnoDB存储引擎使用重做日志来保证数据的持久性
  • 当事务进行数据更改时,这些更改首先记录在重做日志中,这是一种预写式日志,保证即使在提交后立即发生故障,更改也可以从这些日志中恢复

2.日志缓冲(Log Buffer):

  • 更改首先写入到日志缓冲区,这是一种内存中的结构,用于缓存日志记录
  • 为了提高性能,日志缓冲区不是每次事务提交时都写入磁盘,而是定期刷新

3.检查点(Checkpoint)机制

  • 检查点是持久性保证的关键部分,定期将当前内存中的数据状态和重做日志同步到磁盘
  • 通过创建检查点,MySQL确保即使在系统崩溃的情况下,也能从最后一个检查点恢复到一致的状态

3.二进制日志(Binary Log)

  • 除了重做日志,MySQL还使用二进制日志记录所有更改数据的操作
  • 二进制日志主要用于复制和数据恢复,它记录了事务的全部效果,而不仅仅是数据页的更改

MySQL通过结合重做日志、日志缓冲、检查点和二进制日志等机制,提供了强大的持久性保证,确保了事务的永久性和数据的安全性,即使在面临突发的系统故障时也能保持数据的完整性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容