数据库事务的 ACID 特性

题目

数据库事务的 ACID 特性

推荐解析

1)原子性( Atomicity ):确保事务中的所有操作要么全部提交成功,要么全部失败回滚,不会出现部分操作成功部分操作失败的情况。

START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE account_id = 123;
INSERT INTO transaction_log (account_id, amount, transaction_type) VALUES (123, 100, 'WITHDRAW');
COMMIT;

如果任何一个操作失败,整个事务将会回滚,保持数据的一致性。

2)一致性( Consistency ):当事务完成时,数据库从一个一致性状态转移到另一个一致性状态,不会破坏数据库的完整性约束。

START TRANSACTION;
UPDATE orders SET status = 'shipped' WHERE order_id = 456;
INSERT INTO shipping_log (order_id, shipped_date) VALUES (456, NOW());
COMMIT;

当事务完成时,订单状态和发货日志是一致的,不会破坏数据库的完整性约束。

3)隔离性( Isolation ):确保事务之间的操作相互隔离,即一个事务的执行不会受其他事务的影响,每个事务都感觉不到其他事务的存在。

-- 事务1
START TRANSACTION;
SELECT * FROM accounts WHERE account_id = 789 FOR UPDATE;

-- 事务2
START TRANSACTION;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 789;
COMMIT;

事务1对账户进行了锁定,防止其他事务同时修改该账户,确保了隔离性。这里加的是排他锁(独占锁)。

4)持久性( Durability ):一旦事务提交,其所做的修改将会永久保存在数据库中,即使系统发生故障也不会丢失。

面试小技巧

在记忆四大特性的时候,要清楚原理,也就是原子性是基于什么实现的?隔离性是基于什么实现的?持久性是基于什么实现的?一致性是目的,而不是手段!

建议先了解三大日志!!!很重要,我这边作概述。

原子性:要保证原子性,肯定要有事务,要有事务,那么如果出现异常,就要进行回滚,那么谁是回滚日志?

undo log:事务修改会记录到回滚日志中,发生异常,利用回滚日志的信息将数据进行回滚,而且回滚日志又优先于数据持久化到磁盘上。如果数据库宕机,用户再次启动数据库,数据库通过查询回滚日志来回滚尚未完成的事务。

持久性:通过 Redo log 重做日志进行实现,重做日志是 MySQL 的 InnoDB 引擎独有的,如果 MySQL 宕机,重启后读取日志即可恢复。

由于 MySQL 数据以页做单位,查询记录,会加载一页的数据页,然后放到缓冲池( Buffer Pool )中,后续查询先从缓冲池找,没有命中,再硬盘加载,减少 IO 开销,更新数据也是如此,对数据页的修改会记录到重做日志的缓存,redo log buffer 中,然后通过刷盘到 redo log 文件。因为 undo log 频率太低,而 Redo log 能够有效的防止数据的丢失,有兴趣的可以了解下 Redo log 的刷盘策略,默认是事务提交都进行刷盘,这样是最安全的。

下图非常清晰的展示了刷盘的过程,以及 fsync 系统调用。可以去了解下 Read、Select、Epoll 这些调用分别有什么作用,基础还是非常重要的。

图源: Java Guide

隔离性:通过锁机制和 MVCC 机制来实现,而 MVCC 又通过 隐藏字段、undo log、Read View 进行实现。像可重复读和读已提交就是通过 MVCC 机制实现,MVCC 解决的是读写冲突问题,传统读写会阻塞,而 MVCC 读读和读写都不阻塞,写写才会阻塞,因此经常采用 MVCC + 乐观锁/悲观锁。锁解决写写冲突, MVCC 解决读写冲突。通过一个隔离性其实阐述很多知识点,像快照读,当前读,MVCC,悲观锁,乐观锁,ABA 问题,隐藏字段(回滚指针,事务 id,隐藏生成聚簇索引 id ),活跃事务列表,数据可见性算法, RC 和 RR 隔离级别下 MVCC 的差异,MVCC + 间隙锁解决幻读等等,像这些问题你能够通过问一个特性去层层深入,面试官肯定是对你有所赞赏的。

其他补充

鱼聪明AI 的回答:

鱼聪明 AI地址:鱼聪明AI

数据库事务的ACID特性是指原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )和持久性( Durability )。

1)原子性( Atomicity ):确保事务中的所有操作要么全部提交成功,要么全部失败回滚,不会出现部分操作成功部分操作失败的情况。原子性通过日志系统来实现,所有的操作都会被记录在日志中,以便在事务失败时进行回滚,或者在事务提交时将操作应用到数据库中。

2)一致性( Consistency ):当事务完成时,数据库从一个一致性状态转移到另一个一致性状态,不会破坏数据库的完整性约束。数据库在执行事务时会保证数据的完整性和一致性,如果事务执行过程中违反了数据库的约束条件,事务将会被回滚,以保持数据库的一致性。

3)隔离性( Isolation ):确保事务之间的操作相互隔离,即一个事务的执行不会受其他事务的影响,每个事务都感觉不到其他事务的存在。数据库系统通过锁机制来实现事务的隔离性,以防止并发事务之间的数据混乱和不一致性。

4)持久性( Durability ):一旦事务提交,其所做的修改将会永久保存在数据库中,即使系统发生故障也不会丢失。数据库系统会将事务的操作持久化到磁盘上,以确保数据的持久性,即使在系统发生故障或者断电的情况下,数据也不会丢失。

综上所述,数据库事务的 ACID 特性确保了数据的完整性、一致性、隔离性和持久性,使得数据库能够有效地管理并发事务和故障恢复,保证数据的安全性和可靠性。

CSDN某同学的回答:

1)原子性:每个事务中的操作要么全部完成要么全部不执行,保证数据库状态不会因为部分操作失败而改变。

2)一致性:保证所有写入数据库的数据都是合法的,遵守定义好的规则,不会违反约束、级联和触发器等规则。

3)隔离性:并发执行多个事务对系统状态的影响和串行执行多个事务对系统状态的影响是一样的,未完成的事务对其他事务是不可见的。

4)持久性:一旦事务提交,其状态就会永久保存,即使发生主机断电、崩溃或错误。事务的结果必须被记录在永久性存储中。

知乎某同学对一致性的回答:

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

如转账的栗子: 假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

欢迎交流

在阅读本文之后,你应该对了解 AID 是手段,D 是目的,而不能混为一谈,通过一个特性应该分析本质,这个特性怎么实现的?为什么要有这个特性?接下来,我将提出三个问题,欢迎小伙伴在评论区留言进行交流!

1)数据库三大日志有哪些,它们的作用是什么?

2)MVCC 是什么?怎么实现 MVCC ?

3)MVCC 能够解决幻读吗?如果不能,需要和什么配合才能解决幻读问题?