当前位置:首页 > 问答 > 正文

数据库脏读到底是啥,数据怎么会不靠谱,听说这风险还挺大的

综合自IBM技术文档、Oracle官方概念指南、以及《数据库系统概念》一书中的基础解释)

数据库脏读,你可以把它想象成一个特别让人尴尬的场面,假设你和你朋友一起去银行ATM机,他账户里有100块钱,他需要取100块出来急用,于是他走到了ATM机前开始操作,这个时候,你正好在用手机银行APP查他的账户余额,想确认一下他是不是真的有钱还你,关键的时刻来了:你的朋友按下了“确认取款”按钮,ATM机内部的数据库立刻动作,把他的账户余额从100元改成了0元,这个修改操作还没有最终完成(ATM机正在哗啦啦地数钱出钞,或者还需要一个最终的确认步骤才算完全结束),就在这个“钱已扣但事未毕”的极短瞬间,你的手机银行APP刷新了,屏幕上清清楚楚地显示:“当前余额:0元”,你心里咯噔一下:“好家伙,原来是个穷光蛋,没钱还我了!” 但实际情况是,几秒钟后,你的朋友取款操作可能因为某种原因失败了(比如机器故障,钞票卡住了),银行系统撤销了刚才的修改,把他的余额又恢复成了100元,可是你呢?你已经看到了那个“0元”的数据,并且深信不疑,甚至还可能因此引发误会和矛盾。

数据库脏读到底是啥,数据怎么会不靠谱,听说这风险还挺大的

这个“0元”的数据,就是典型的“脏数据”,而你在这个错误数据被纠正之前读到它的行为,脏读”,这个数据是“不靠谱”的,因为它根本就不是最终确定的、真实的结果,它就像一个还在草稿纸上涂涂改改的数字,却被你当成正式公告给看了去。

数据怎么会变得这么不靠谱呢?根源在于数据库为了让大家都能快速访问,允许很多事情同时发生(这叫做“并发操作”),就像很多人可以同时在网上买同一场演唱会的票一样,为了保证速度,数据库不会总是让一个人完全办完事再轮到下一个人,那样效率太低了,它会穿插着进行,问题就出在这种“穿插”的时机上,如果一个操作(比如你朋友的取款)刚刚写了一部分数据(把余额改成0),但还没有最终提交(确认操作成功),而另一个操作(你的查询)在这个时候插进来,直接读取了那个中间状态的、未提交的数据,脏读就发生了,这个未提交的数据是极度危险的,因为它随时可能被撤销,让它就像从来没存在过一样,但它已经对你造成了影响。

数据库脏读到底是啥,数据怎么会不靠谱,听说这风险还挺大的

听说这风险还挺大的,一点都没错,脏读带来的可不是小麻烦,它在现实世界中可能引发非常严重的后果,想象一下这些场景:

  1. 财务计算错误: 比如公司的财务系统正在做月末结算,一个操作员正在调整一批货物的成本价,他先暂时把某个商品的成本改成了一个很高的数字,但还在核对其他数据,没有最终确认,就在这时,另一个生成财务报表的程序运行了,它读到了这个被临时调高的成本,导致计算出的毛利率严重失真,公司管理层基于这份错误的报告可能会做出完全错误的决策,比如错误地判断某个产品线亏损而将其关闭,但实际上它是盈利的。

    数据库脏读到底是啥,数据怎么会不靠谱,听说这风险还挺大的

  2. 超额售卖或库存混乱: 比如机票预订系统或者热门商品抢购,假设最后一张机票,两个客户几乎同时下单,系统处理第一个订单时,先将座位状态标记为“已预订”(但未最终出票),第二个客户查询时,如果读到了这个“已预订”的脏数据,系统就会显示无票,导致他放弃购买,但如果第一个客户的订单因为支付失败而被取消,座位状态会恢复为“可售”,而第二个客户早已离开,这就造成了座位空置和销售收入损失,反过来,如果系统没处理好,也可能出现一票两卖的情况。

  3. 数据依赖导致的连锁错误: 这是更隐蔽也更可怕的风险,假设有一个统计程序,它的任务是先读取用户A的账户积分,然后根据这个积分值去更新用户A的等级,不巧的是,在它读取积分的那一刻,正好有另一个操作在修改A的积分(比如扣除因违规操作产生的积分),而且这个修改还未提交,统计程序读到了一个“脏”的积分值(比如还是违规前的较高分数),然后依据这个错误的高分数,将用户A错误地提升到了一个他本不该达到的高等级,之后,即使用户的积分被正确扣除了,那个错误提升的等级也可能一直留在系统里,导致他享受不应有的特权,一个错误引发了另一个错误,像多米诺骨牌一样。

正因为脏读有这么大的潜在危害,数据库的设计者们才发明了各种“隔离级别”来防止它,最简单粗暴的办法就是“串行化”,也就是强制所有操作一个一个排队执行,绝对不穿插,这样肯定没有脏读了,但效率会变得极低,就像只有一个柜台的银行,队伍排得老长,在实际应用中,数据库通常会提供一些折中的选项,读已提交”隔离级别,在这个级别下,一个操作只能读到那些已经被其他操作“最终确认”(提交)的数据,像那种临时修改的、未提交的脏数据是绝对读不到的,这就好比规定,手机银行APP只能查询已经完全结束的交易产生的余额,对于那些正在进行中、可能被撤销的操作所产生的中间数据,一律不可见,这样就从根本上杜绝了脏读的发生,保证了核心数据的靠谱性。

数据库脏读就是因为在多人同时操作数据库时,读到了别人还没最终敲定的、可能随时会变卦的“草稿数据”,这些数据极其不靠谱,因为它们不代表最终事实,而它的风险之所以大,是因为它能让企业基于错误信息做决策,导致财务损失、业务混乱和难以追溯的连锁错误,理解并防范脏读是确保信息系统数据可靠性的关键一环。