数据库的ACID是怎么实现的

A 原子性 C 一致性 I 隔离性 D 持久性
已Mysql的innerDb 来分析
一致性是最终要达到的业务目标,原子性、隔离性、持久性是数据库用来保证一致性的技术手段。
(1)原子性 就是说一个事务里的所有操作,要么全部生效,要么通过事务回滚撤销修改。
数据库是怎么回滚的,就是靠回滚日志(undo log),修改时,innodb会记录撤销修改所需要的信息,可以理解为一份恢复说明。
比如,你新增一条记录,它就记录一条删除,如果你修改字段1->0,它就记录一条改回:0->1。
撤销修改就靠undo log回滚,崩溃恢复,还需要靠redo log 重做已提交。
(2)持久性, 修改应在故障后恢复,这里说的是收到提交成功,而不只是发出了提交请求。
数据库的数据最终要存在磁盘的大文件里,如果每次提交事务,都要立刻去磁盘里翻找对应的数据页做修改,这种大量的随机写操作速度会非常慢。
为了平衡性能和数据安全,数据库采用预写式数据日志,也就是常说的WAL,它把变动记录到重做日志,也就是redo log.
关键是数据页刷盘前,对应日志必须先落盘。日志顺序写通常比零散刷数据页更高效。在提交时刷盘的配置下,提交过程会等待相关redo持久化。
如果开启binlog,还要协调两类日志。万一这时候服务器宕机,重启后数据库会自动翻开重做日志,把还没来得及同步到磁盘大文件里的数据重新补齐,支持了持久性。
不过它依赖正确的刷盘配置和可靠的存储,不能承诺磁盘损坏也不丢数据。
(3)隔离性,显示业务里往往会有很多请求同时读写数据,隔离性控制并发事务能看到什么、怎么相互影响,具体保证取决于隔离级别。
比如读已提交能避免脏读,读未提交却允许脏读。面对并发冲突,数据库分了两种情况来处理。如果是事务同时想改同一行数据,也就是写写冲突,那就只能委屈一下锁机制,
让后来的事务排队等待,保证同一时间只有一个人能改。但如果是一个事务在写、一个事务在读呢,要是读操作也跟着排队加锁,系统的吞吐量就会急剧下降。
这时候Mysql推出了一个关键机制,叫做多版本并发控制,叫做MVCC,它巧妙利用了前面提到的回滚日志,把数据的历史修改版本串联起来。
这样一来,在读已提交和可重复读下,普通一致性读根据读视图选择可见版本,必要时沿undo记录重建旧版本,减少读写阻塞。
但加锁读和更新仍要参与锁竞争。

他们的因果性:
如果原子性没做好,事务中途失败没能回滚,余额对不上,数据就失去了一致性,如果持久性没做好,断电导致提交的数据丢失,一致性同样不复存在;
如果隔离性没做好,并发读到脏数据,业务结果依然会出错。
正是因为回滚日志守住了原子性,重做日志守住了持久性,锁和MVCC守住了隔离性,这些机制协调工作,为一致性提供保障。
但是如果转账代码本来就把扣款和入账金额写得不一样,数据库也不会自动帮你纠正业务逻辑。
实际架构设计要考虑资源与性能的取舍,比如重做日志落盘,要考虑磁盘I/O成本,加锁会降低写入吞吐,而MVCC也需要在不同的隔离级别下选不同的读视图时间和可见性规则。

posted @ 2026-09-14 22:26  堭鍙銤  阅读(6)  评论(0)    收藏  举报