新手心得:数据库事务到底在保证什么

举报
yd_273029183 发表于 2026/11/07 22:13:47 2026/11/07
【摘要】 想象你在手机银行上给朋友转 500 块:你的账户减 500,对方的账户加 500。这两件事必须同进同退——只做一半,钱就会凭空消失或凭空变出来。数据库里把这样一组“要么全做、要么全不做”的操作打包在一起,就叫一个事务。转账、买票、下单扣库存,背后都是事务在撑着。这套用了几十年的约定,名字叫 ACID。ACID 是四个英文词的首字母,1983 年由 Härder 和 Reuter 在一篇讲数据...

想象你在手机银行上给朋友转 500 块:你的账户减 500,对方的账户加 500。这两件事必须同进同退——只做一半,钱就会凭空消失或凭空变出来。

数据库里把这样一组“要么全做、要么全不做”的操作打包在一起,就叫一个事务。转账、买票、下单扣库存,背后都是事务在撑着。这套用了几十年的约定,名字叫 ACID。

ACID 是四个英文词的首字母,1983 年由 Härder 和 Reuter 在一篇讲数据库恢复的论文里正式提出,源头是更早的 Jim Gray 对可靠事务系统的描述。四个字母,就是事务要兑现的四句承诺。

第一句是原子性:事务里的操作是一个整体,不可再拆。执行中途出错,数据库会把已经做了一半的修改全部撤销,退回事务开始前的样子,这个动作叫回滚。所以你永远不会看到“钱扣了、对方没收到”这种半截状态。

第二句是一致性:事务执行前后,数据都要符合既定的规则。账户余额不能是负数、订单总价要等于各项之和,这些规则叫约束和业务逻辑。原子性、隔离性、持久性其实都是在为一致性服务。但要注意:数据库只能守住它知道的规则,“该不该转这笔钱”是应用程序的判断。事务能保证数据不被写坏,保证不了业务逻辑本身写错了。

第三句是隔离性:好几个事务同时跑的时候,彼此不能互相捣乱。只剩最后一张票,两个人同时下单,隔离性要保证最终只卖出一张,而不是两人都以为自己抢到了。完全隔离最安全,但代价是大家要排队等,速度变慢。所以数据库一般提供几档隔离级别,从宽松到严格:读未提交、读已提交、可重复读、串行化。级别越低越快,但可能看到别人还没提交的中间结果;级别越高越稳妥,但越慢。选哪一档,是在正确和速度之间取舍,而不是越高越好。

第四句是持久性:事务一旦提交成功,结果就不能再丢。哪怕下一秒服务器断电、硬盘出问题,提交过的数据也必须还在。常用办法是先写日志再落盘:提交之前,先把改动记进一份专门的日志,机器重启后照着日志把没写完的活补上。

工作流程也随之清楚了:开始事务,做一连串读写;都顺利就提交,改动正式生效;中途出错就回滚,当作什么都没发生过。提交和回滚,就是事务的全部开关。

不过也有几个常见误解值得说清楚。

一是“支持 ACID”不等于“万无一失”。不同数据库对 ACID 的实现程度并不一样,隔离级别、日志策略不同,实际保证的强度就有差别。看到宣传语说支持 ACID,先问一句默认是哪一档隔离级别、崩溃后怎么恢复,不能只看四个字母就放心。

二是事务不是越长越好。把几百个操作塞进一个事务里,锁住的数据就多、占用的时间就长,别人只能在外面排队。事务尽量短:只包真正必须同进同退的那几步,做完赶紧提交。

三是单机事务的办法不能直接搬到跨库、跨服务上。一旦改动分布在多个数据库、多个系统里,“要么全做、要么全不做”就难得多,需要另外的协调机制,有些场景只能接受“最终一致”而不是“立刻一致”。后来出现的 BASE 思路——基本可用、软状态、最终一致——和 ACID 正好是两条路线。

说到底,事务解决的是一个朴素的问题:现实里的很多事本来就是“一组动作”,拆开做就会出乱子。ACID 把这组动作绑成一个整体,省去了程序员自己处理断电、并发、半截写入的麻烦。下次遇到“这两个操作必须一起成功”,先想想能不能放进一个事务里。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。