数据库事务、分布式事务

85 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第25天,点击查看活动详情

数据库事务

大多数情况下,我们在谈论事务的时候,如果没有特指分布式事务,往往指的就是数据库事务

数据库事务在我们日常开发中接触的最多了。如果你的项目属于单体架构的话,你接触到的往往就是数据库事务了。

那数据库事务有什么作用呢?

简单来说,数据库事务可以保证多个对数据库的操作(也就是SQL语句)构成一个逻辑上的整体。构成这个逻辑 上的整体的这些数据库操作遵循:要么全部执行成功,要么全部不执行。

 # 开启一个事务
 START TRANSACTION;
 # 多条 SQL 语句
 SQL1,SQL2...
 ## 提交事务
 COMMIT;

image.png

另外,关系型数据(例如:MySQL、SQL Server、Oracle 等)事务都有ACID特性:

  1. 原子性 (Atomicity ):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
  2. 一致性Consistency): 执行事务前后数据保持一致,例如转账业务中无论事务是否成功,转账者和收款人的总额应该是不变的;
  3. 隔离性Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
  4. 持久性Durabilily): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

这里要额外补充一点:只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。也就是说 A、I、D 是手段,C 是目的!

想必大家也和我一样,被ACID 这个概念被误导了很久! 我也是看周志明老师的公开课《周志明的软件架构课》才搞清楚的(多看好书!!!)。

image.png

数据事务的实现原理呢?

我们这里以MySQL的InnoDB引擎为例来简单说一下。

MySQL InnoDB引擎使用 redo log(重做日志) 保证事务的持久性,使用 undo log(回滚日志) 来保证事务的原子性。

MySQL InnoDB引擎通过 锁机制MVCC 等手段来保证事务的隔离性(默认支持的隔离级别是REPEATABLE-READ)。

分布式事务

微服务架构下,一个系统被拆分为多个小的微服务。每个微服务都可能存在不同的机器上,并且每个微服务可能都有一个单独的数据库供自己使用。这种情况下,一组操作可能会涉及到多个微服务以及多个数据库。

举个例子:电商系统中,你创建一个订单往往会涉及到订单服务(订单数加一)、库存服务(库存减一)等等服务,这些服务会有供自己单独使用的数据库。

image.png

那么如何保证这一组操作要么都执行成功,要么都执行失败呢?

这个时候单单依靠数据库事务就不行了!我们就需要引入 分布式事务 这个概念了!

实际上,只要跨数据库的场景都需要用到引入分布式事务。比如说单个数据库的性能达到瓶颈或者数据量太大的时候,我们需要进行 分库。分库之后,同一个数据库中的表分布在了不同的数据库中,如果单个操作涉及到多个数据库,那么数据库自带的事务就无法满足我们的要求了。

image.png

一言蔽之,分布式事务的终极目标就是保证系统中多个相关联的数据库中的数据的一致性!

那既然分布式事务也属于事务,理论上就应该准守事务的 ACID 四大特性。但是,考虑到性能、可用性等各方面因素,我们往往是无法完全满足 ACID 的,只能选择一个比较折中的方案。

针对分布式事务,又诞生了一些新的理论。

分布式事务基础理论

CAP理论和BASE理论

CAP 理论和 BASE 理论是分布式领域非常非常重要的两个理论。不夸张地说,只要问到分布式相关的内容,面试官几乎是必定会问这两个分布式相关的理论。

不论是你面试也好,工作也罢,都非常有必要将这两个理论搞懂,并且能够用自己的理解给别人讲出来。

我这里就不多提这两个理论了,不了解的小伙伴,可以看我前段时间写过的一篇相关的文章:《CAP 和 BASE 理论了解么?可以结合实际案例说下不?》

一致性的 3 种级别

我们可以把对于系统一致性的要求分为下面3种级别:

  1. 强一致性:系统写入了什么,读出来的就是什么。
  2. 弱一致性:不一定可以读取到最新写入的值,也不保证多少时间之后读取到的数据是最新的,只是会尽量保证某个时刻达到数据一致的状态。
  3. 最终一致性:弱一致性的升级版。系统会保证在一定时间内达到数据一致的状态

除了上面这 3 个比较常见的一致性级别之外,还有读写一致性、因果一致性等一致性模型,具体可以参考《Operational Characterization of Weak Memory Consistency Models》这篇论文。因为日常工作中这些一致性模型很少见,我这里就不多做阐述。

业界比较推崇是 最终一致性,但是某些对数据一致要求十分严格的场景比如银行转账还是要保证强一致性。

柔性事务

互联网应用最关键的就是要保证高可用, 计算式系统几秒钟之内没办法使用都有可能造成数百万的损失。在此场景下,一些大佬们在 CAP 理论和 BASE 理论的基础上,提出了 柔性事务 的概念。 柔性事务追求的是最终一致性。

实际上,柔性事务就是 BASE 理论 +业务实践。 柔性事务追求的目标是:我们根据自身业务特性,通过适当的方式来保证系统数据的最终一致性。 像 TCC、Saga、MQ 事务 、本地消息表 就属于柔性事务。

刚性事务

与柔性事务相对的就是 刚性事务 了。前面我们说了,柔性事务追求的是最终一致性。那么,与之对应,刚性事务追求的就是 强一致性

2PC 、3PC 就属于刚性事务。