从Paxos到Zookeeper 读书笔记(1)-事务的ACID

首先,要注意的是C In CAP ≠ C in ACID,这两个C是不同含义的,不要搞错。

事务的四大特征ACID

分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),一个支持事务的数据库必须要具有这四种特征,否则在事务过程(Transaction processing)当中无法保证数据的正确性。

原子性

是指事务中包含的各项操作在一次执行过程中,只允许出现以下两种状态之一:

  • 全部成功执行
  • 全部不执行

任何一项操作失败会导致整个事务失败,其他已执行的操作将被撤销并回滚。

一致性

事务的执行不能破坏数据库的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。

例子:在下面的例子中数据库表有两列,A 和 B 。数据完整性约束要求 A 列的值和 B 列的值之和必须等于 100 。下面的 SQL 语句创建了一张表,这张表满足约束条件:A+B=100 。

CREATE TABLE acidtest (A INTEGER, B INTEGER, CHECK (A + B = 100));
一致性是个非常泛化的术语,它要求数据必须满足所有的合法规则。以前面的例子为例,合法性规则是要求 A + B = 100 ,同时 A 和 B 还必须为整数。 所有的合法规则必须都被检查从而确保了事务的一致性。假设一个事务尝试着从 A 中减去 10 而不修改 B ,有效性校验会发现 A + B = 90 ,这与数据库的约束规则不一致,整个事务必须被取消,被影响到的行回滚到执行事务之前的状态(这里也体现了原子性)。如果还有其他约束、触发器、级联,每一个独立改变的操作在事物被提交之前必须像前面一样进行一致性检查。

隔离性

并发环境下,隔离性保证并发执行多个事务对系统的状态的影响和串行化执行多个事务对系统的状态的影响是一样的。隔离性是并发控制的主要目标,通过并发控制的方法,一个未完成的事务的影响对其他事务是不可见的。

上述的隔离性主要指强隔离性。一个弱的隔离性能保证同一时间多个用户能同时对一块数据进行操作,但可能会造成遇到很多并发影响(如:读脏数据、丢失修改等)。一个强的隔离性能减少用户遇到的并发影响,但是会增加事务阻碍其他事务的几率。

在标准SQL规范中,定义了4个事务隔离级别,分别是读未提交(Read uncommitted)、读提交Read committed)、重复读(repeatable)和序列化(Serializable)。

  • 读未提交

读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。

事例:老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。

分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读


那怎么解决脏读呢?Read committed!读提交,能解决脏读问题。


  • 读提交

读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。程序员就会很郁闷,明明卡里是有钱的…

分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读


那怎么解决可能的不可重复读问题?Repeatable read !


  • 重复读

重复读,就是在开始读取数据(事务开启)时,不再允许修改操作

事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。

分析:重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作

什么时候会出现幻读?

事例:程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录(全表扫描FTS,妻子事务开启),看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。


那怎么解决幻读问题?Serializable!


  • 序列化
Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
值得一提的是:大多数数据库默认的事务隔离级别是Read committed,比如Sql Server , Oracle。Mysql的默认隔离级别是Repeatable read。

ANSI SQL隔离级别


持久性

事务的持久性是指,一个事务一旦被提交,它对数据库中对应数据的更改就是永久性的。即使发生系统崩溃或者宕机,只要数据库能够重启,就一定能恢复到事务结束时的状态。


隔离部分转载:http://blog.csdn.net/qq_33290787/article/details/51924963


猜你喜欢

转载自blog.csdn.net/u013885699/article/details/79646689