原子性(Atomicity)

要么全做,要么全不做的规则称之为原子性。两个事务要么全部成功,要么全部失败,不能存在中间状态。

数据库中的一条操作也可能被分解成若干个步骤(比如先修改缓存页,之后再刷新到磁盘等),在任何一个可能的时间都可能发生意想不到的错误(可能是数据库本身的错误,或者是操作系统错误,甚至是直接断电之类的)而使操作执行不下去。

mysql是如何实现这种特性的?redo log(事务的两阶段提交——事务回滚、发生操作系统故障,记录未来得及从Buffer Pool刷新到磁盘的数据刷新到磁盘【记录的是那一页一行修改了什么字段的数据】)和 undo log(MVCC多版本事务控制,用于事务回滚)

隔离性(Isolation)

事务是独立的,之间互相不影响。

以转账为例,A向B连续转两次帐:

下边几个步骤组成的:

  • 步骤一:读取A账户的余额到变量A中,这一步骤简写为read(A)
  • 步骤二:将A账户的余额减去转账金额,这一步骤简写为A = A - 5
  • 步骤三:将A账户修改过的余额写到磁盘里,这一步骤简写为write(A)
  • 步骤四:读取B账户的余额到变量B,这一步骤简写为read(B)
  • 步骤五:将B账户的余额加上转账金额,这一步骤简写为B = B + 5
  • 步骤六:将B账户修改过的余额写到磁盘里,这一步骤简写为write(B)

我们将A向B同时进行的两次转账操作分别称为T1T2,在现实世界中T1T2是应该没有关系的,可以先执行完T1,再执行T2,或者先执行完T2,再执行T1,对应的数据库操作就像这样:

什么是事务?-小白菜博客
但是很不幸,真实的数据库中T1T2的操作可能交替执行,比如这样:

image_1d1sut47o5tk13ul4gb1qibuct2j.png-67.9kB

mysql是如何实现这种特性的? 加锁和MVCC机制

一致性(Consistency)

如果数据库中的数据全部符合现实世界中的约束(all defined rules),我们说这些数据就是一致的,或者说符合一致性的。

  • 数据库本身能为我们保证一部分一致性需求(就是数据库自身可以保证一部分现实世界的约束永远有效)。

    我们知道MySQL数据库可以为表建立主键、唯一索引、外键、声明某个列为NOT NULL来拒绝NULL值的插入。比如说当我们对某个列建立唯一索引时,如果插入某条记录时该列的值重复了,那么MySQL就会报错并且拒绝插入。

  • 更多的一致性需求需要靠写业务代码的程序员自己保证。

原子性隔离性都会对一致性产生影响,比如我们现实世界中转账操作完成后,有一个一致性需求就是参与转账的账户的总的余额是不变的。如果数据库不遵循原子性要求,也就是转了一半就不转了,那最后就是不符合一致性需求的;类似的,如果数据库不遵循隔离性要求,就像我们前边唠叨隔离性时举的例子中所说的,最终A账户中扣的钱和B账户中涨的钱可能就不一样了,也就是说不符合一致性需求了。

原子性隔离性都会对一致性产生影响,比如我们现实世界中转账操作完成后,有一个一致性需求就是参与转账的账户的总的余额是不变的。如果数据库不遵循原子性要求,也就是转了一半就不转了,也就是说给狗哥扣了钱而没给猫爷转过去,那最后就是不符合一致性需求的;类似的,如果数据库不遵循隔离性要求,就像我们前边唠叨隔离性时举的例子中所说的,最终狗哥账户中扣的钱和猫爷账户中涨的钱可能就不一样了,也就是说不符合一致性需求了。

持久性(Durability)

每条事务的执行结果最终都会保存在磁盘上,永久性保存。

持久性意味着该转换对应的数据库操作所修改的数据都应该在磁盘上保留下来,不论之后发生了什么事故,本次转换造成的影响都不应该被丢失掉