我们知道,事务有四个基本特性:ACID;
ACID 特性中的 AID 都很好理解,约等于字面意思,唯独 C(一致性)
众说纷纭,几乎是各有各的说法,这里简单说两句村长的理解吧:
我们先来看一下ACID具体指什么。
关于事务的ACID:
- Atomicity ) 原子性: 事务是最小的执行单位,不允许分割。原子性确保动作要么全部完成,要么完全不起作用;
- Consistency)一致性: 将数据库的数据,从【一个有效的状态】转移成【另一个有效的】状态。
- Isolation)隔离性: 并发访问数据库时,一个事务不被其他事务所干扰。
- Durability)持久性: 一个事务被提交之后。对数据库中数据的改变是持久的,即使数据库发生故障。
从上可以看出,AID 都很好理解,几乎没什么歧义,但一致性这个解释,会让很多人搞不清楚。
关于事务的一致性,比较官方的说法是:指事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态;
挺拗口的,理解上也很迷惑,还是看看维基百科的英文原版吧:
In database systems, consistency (or correctness) refers to the requirement that any given database transaction must change affected data only in allowed ways. Any data written to the database must be valid according to all defined rules,
including constraints, cascades, triggers, and any combination thereof
. Thisdoes not guarantee correctness of the transaction in all ways the application programmer might have wanted
(that is the responsibility of application-level code) but merely that any programming errors cannot result in the violation of any defined database constraints.
Consistency can also be understood as after a successful write, update or delete of a Record, any read request immediately receives the latest value of the Record
.
在数据库系统中,一致性是指任何给定的数据库事务必须以被允许的方式更改受影响的数据。根据所有定义的规则,写入数据库的任何数据都必须有效,包括约束、级联、触发器及其任何组合
。这并不能保证应用程序程序员所希望的所有事务的正确性
(这是应用程序的代码的责任),而仅仅是任何编程错误都不会导致违反任何定义的数据库约束;
一致性也可以理解为在成功写入、更新或删除记录后,任何读取请求都会立即收到记录的最新值。
参考链接: https://en.wikipedia.org/wiki/Consistency_(database_systems)
从英文版的解释可以看出,这个所谓的一致性,其实是指数据库自己可控制的范围,而非通过应用程序代码去控制的范围,当然,也可以使用代码控制。
简单点儿说就是:所有可能违反现有数据库约束规则的事务提交都不会被执行。
并且,通过这两段原文可以看出,一致性,其实会细分为【写一致性】和【读一致性】;
写一致性
比如购物场景,如果用户下单买苹果时,去查库存apple_cnt
,发现库存0
个,但是代码逻辑直接这么写:apple_cnt = apple_cnt-1
,如果数据库没有添加任何约束,则apple_cnt
会被更新为-1
,这个很明显不符合现实生活中的逻辑。
如果你对数据库的库存量添加了约束,约束只能大于等于0,那么此事务就不会被执行,数据库不会出现-1
的库存量,因为它违反了事务的一致性规则(-1
并不是一个有效的数据状态)。
再看另一个场景:
1、有两个表(员工表 & 职位表),员工表中有员工ID、姓名、职位ID等属性,职位表中有职位ID、职位名称、职级等属性;
2、为员工表创建了职位ID的外键约束,依赖于职位表的ID;
3、向员工表中插入一个新员工,但职位ID却不存在于职位表(公司新创建的职位,但尚未入库);
此时,如果没有外键一致性的保证,就会出现,虽然新增了一个员工,但却不知道他是什么职位的情况!
读一致性
读一致性也是数据库一致性的一个重要方面:
我们对一个表中的某些数据进行了更新操作,但是还没有进行提交,这时另外一个用户读取表中数据,就会出现读一致性的问题:到底该读什么时候的数据,是更新前的还是更新后的?
在DBMS中设有临时表,它用来保存修改前的值,在没有进行提交前读取数据,会读取临时表中的数据,这样一来就保证了数据是一致的(当前用户看到的是更新前的值);
还有一种情况:
用户user1对表进行了更新操作,用户user2在user1还没有进行提交前读表中数据,而且是大批量的读取(打个比方,耗时3分钟),而在这3分钟内user1进行了提交操作,那又会产生什么影响呢?这个时候怎么保证读写一致性呢?
这个时候DBMS就要保证有足够大的临时表来存放修改前的数值,以保证user2读取的数据是修改前的一致数据,然后下次再读取时候就是更新后的数据了。
关于 读一致性 的详细介绍可参考 INNODB锁 的并发问题
网友评论