likes
comments
collection
share

mysql事务“一致性”理解

作者站长头像
站长
· 阅读数 12

前言

谈起mysql事务的特性,人尽皆知的就是四个特性:ACID,原子性、一致性、隔离性、持久性。其中原子性、隔离性、持久性理解起来相对直观,各个地方对它们的定义也比较统一。相比之下“一致性”则显得不那么直观,你似乎好像明白它的意思,但是真的让你讲你又说不出来。本文就来探究一下数据库中的"一致性"到底是什么意思。


一、为什么会有事务?

很多人以为''事务''的概念是天然存在的,就像空气一样理所当然的存在。

实际上并非如此,之所以出现事务是因为:当应用程序访问数据库时,事务能够简化编程的步骤,不必考虑各种潜在的错误和并发问题。

我们使用事务时,要么回滚,要么提交。只用处理业务问题,而不必关注网络抖动或者物理机器问题。不用没完没了的try..catch和异常判断。事务是为了服务应用层诞生的,并非伴随着数据库系统出现。 如果没有事务,那就必须用代码去保证数据的完整性和准确性。这绝对会是程序员的灾难。

二、为什么"一致性"很难理解?

我觉得一致性难理解有两个方面的原因。

“一致性”的意义被泛化

各种系统、各种设计中都在使用“一致性”的概念。目前起码有四种一致性的概念。

  • ACID中的一致性
  • 一致性哈希
  • CAP定理的一致性
  • 分布式多副本一致性

其中CAP的一致性是指线性一致性,主要描述了在故障和延时下的副本之前的协同问题。一致性哈希是为了解决分布式缓存问题。分布式多副本一致性则是保持分布式系统中各个节点之间的数据一致。

上边这些都不是ACID中的一致性的含义,但是你也不能完全说一点关系也没有。很多人把数据库的一致性和其他一致性概念混淆,所以经常迷迷糊糊的,说也说不清。

数据库一致性有两层含义

数据库的一致性其实包含两个层面。从数据库层面理解,“一致性”实际上是一组约束、规则。从业务层面讲,“一致性”实际上是指事务把数据库从一个有效的状态转移成另一个有效状态。

一致性一种约束

从数据库的角度来看,它只关心transcation是否符合定义好的规则,如果符合规则,那么就是符合一致性的。

那么这些规则是什么?它可以是约束,可以是CASCADE(在父表上update/delete记录时,同步update/delete掉子表的匹配记录),也可以是trigger。亦或者是它们的组合。

用商品库存的例子来说。当库存>=1时表示有商品,此时可以售卖。库存=0表示没有商品不能售卖。根据我们朴素的生活经验,库存不能小于0

因此,我们的数据库对商品数量进行约束,使其数量大于等于0。当库存=0时,倘若还执行update good_table set good_number=good_number-1语句,数据库会拒绝执行,因为这破坏了“一致性”。

从数据库的角度来说,它认为的一致性就是如此。但是,对于业务上的逻辑,数据库并不知晓,它也不会关注。比如,两个用户同时在某一时刻对库存减一,导致某个用户的减库存操作被另一个用户覆盖(经常发生的超卖问题就是如此,比如前两天到处都能看到的名为“秒杀飞天茅台超卖”的文章)。数据库并不能抵御这种错误的发生。

这就是我马上要讲的,一致性是一种目的。

一致性是一种目的

从更高层面来讲,“一致性”是编程过程中,想要达成的一种目的。保证事务只能从一个正确的状态转移到另一个正确的状态。

什么是正确的状态?

数据库用一定的模式存储数据,本质上是对真实世界的建模,是物理世界的映射。当数据库中的状态与现实世界的数据状态保持一致时,数据库就是正确的状态。

上边的话可能有点抽象,没关系,我举个例子。我们还转账的例子来说,假设A的银行账户有500元,B的账户为0元。A通过网络给B转账100元。转账的过程一定分为两个阶段,第一从A的账户里扣100元,第二给B的账户加100元。如果过程顺利,A的账户变400元,B的账户为100元。

然而如果出现“一致性”问题,则有可能出现A的账户变400元,但是B的账户还是0元。这种情况在现实世界绝对不会发生,100元的钞票要么已经递到了B手上,要么还是在A手上,无论如果都不会有A的100元莫名其妙不见了,而B手上也没有100元的情况。除非是见了鬼......(ps:这种情况下还是别讨论啥一致性问题了,赶紧去配个眼镜,这样能控制近视的度数)。

和真实世界保持一致,就是正确的状态。

此时的“一致性”是一种目的,单靠数据库是完不成的,但偏偏数据库又是“一致性”的表现载体。那么,如何达到这种一致性呢?

!!此时,要靠各种锁达成一致性,悲观锁(select xxx from xxx for update)、乐观锁(mvcc,select xxx from xxx lock in share mode)等等,这个就说来话长了,改日另起一篇吧。

总结

“一致性”概念泛滥,要清楚地将数据库的“一致性”与其他“一致性”区分。数据库的”一致性“从底层来说,是一组约束。这组约束可以是约束条件、可以是触发器等,也可以是它们的组合。从更高的层面来说,“一致性”是一种目的,即保持数据库与真实世界之间的正确映射。此时,需要靠各种锁来达成“一致性”。