很多人以为 ACID 只是数据库教科书里无关紧要的四个字母,但在金融系统里,少了其中任何一个,都可能造成不可挽回的灾难。这个 1983 年由 Andreas Reuter 和 Theo Härder 提出的概念,至今仍然是所有依赖强数据一致性的系统必须遵守的底线。它不是某种可选的性能优化,而是一套事务执行的基本“体能测试”:只要涉及钱、账户、库存、任何需要精确对账的场景,ACID 就是绕不开的门槛。
先搞清楚 ACID 到底是什么。Atomicity、Consistency、Isolation、Durability,也就是原子性、一致性、隔离性、持久性。这四者共同定义了一个“事务”应该怎样被处理。所谓事务,就是一次有明确边界的操作序列,比如从 A 账户转 100 元到 B 账户,这必须是一个不可拆分的工作单元。ACID 把这套规则变成了数据库层面的硬约束,最初被所有关系型数据库(Postgres、MySQL 等)完整采纳,后来连 MongoDB、FoundationDB 等非关系型数据库也开始将它作为基础保证,尽管有些实现上还是“部分支持”。
下面把这四个字母一个个拆开,看它们分别管什么,以及缺了任何一个会出多大的乱子。
Atomicity(原子性):不成功,就完全退回
原子性指的是一件事务要么全部执行,要么完全不执行,不存在“只执行了一半”的状态。这不是一句轻飘飘的口号。设想一个在线商城的下单流程:既要扣除优惠券,又要更新库存,还要生成订单,这三步如果中间因为崩溃或者断电断了,系统就必须把已经执行的部分全部回滚,恢复到事务开始前的样子。如果没有原子性,就可能出现库存已经扣了,但订单没生成,优惠券却白白消耗掉——数据不一致的烂摊子,纠正的成本远比当初老老实实遵守规则高。很多人在早期用简单的文件存储做业务时,就是在“部分写入”上栽了跟头。
Consistency(一致性):不是靠自觉,是靠约束
一致性指的是事务执行前后,数据必须始终遵守预先定义的规则,也就是所有完整性约束都要满足。比如开店,你要让一个客户成功下单,就必须先有这个客户的账号,这就是一条“下单必须关联用户”的规则。在数据库里,这种规则最常用的实现就是外键(FK)。一致性不是凭空而来的,它需要你在一开始就把业务规则翻译成数据库约束,否则单靠程序逻辑来兜底,迟早会出现垃圾数据。更致命的是,一旦数据坏了,后续的分析、报表、推荐全都建立在沙子上。
Isolation(隔离性):你的操作,别踩到别人的脚
隔离性说的是,并发执行的事务之间不能互相干扰。你查用户信息的同时,另一个人在修改同一条数据,两个操作的结果不应该因为时序而乱掉。典型的例子就是两个用户同时在抢最后一件库存,如果隔离级别不到位,可能就会出现“都以为抢到了”的闹剧。隔离性的实现有不同档次,比如读已提交、可重复读、串行化,每一个档次都在一致性要求和性能之间做了取舍,但核心思想都一样:让每个事务以为自己是独享数据库的,直到最终结果按照预期顺序落定。
Durability(持久性):一旦确认,就钉死在那里
持久性是最直观但又最容易因为硬件故障被忽略的一条。它要求一旦事务提交成功,数据就必须被永久保存,即使下一秒服务器断电、磁盘损坏,也不能让已经确认的数据丢失。数据库通常通过写入事务日志(WAL)来实现这一点,哪怕内存中的数据还没刷到磁盘,只要日志还在,重启后就能恢复到一致状态。对于金融系统来说,持久性就是最后一道防线:转账完成,记录就必须活着,否则银行真得关门。
这四个属性的最终目标其实就一个:让开发者可以像操作单线程单用户一样去写业务逻辑,而不必在每一行代码里垫一层异常补救。虽然某些场景下可以适当放宽 ACID(比如一些日志采集、社交动态流,实时性大于一致性),但只要数据一旦和金钱、权益、身份绑定,ACID 就不该是被讨论“要不要”的问题,而只应该是“怎么实现得更好”的技术工程。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.