目录
一:数据库事物的实现与缺陷
1.mysql事物解决的问题
2.事物回滚的理论机制
3.事物特性的协作性。
二:分库,分表的事物的实现
1.实现的场景
2.解决方案
3.2p式提交的理论
4.2p式提交的缺点
三:分布式事物
1.分布式理论的提出
2.CAP理论的选择
3.如何实现高可用的A理论
4.分布式事物的实现
官方定义中:事物是用来解决mysql中的幻读,脏读,不可重复读。简而言之,当有多个客户端对数据库进行查询或者修改新
增修改操作时,会产生不同步信息,导致查询结果不一致。其实我认为吧还有一种比较重要的方式事物回滚,就是当你直接
进行增删改时,允许结果错误时进行回滚。
事物回滚的外在表现: 在开启事务的时候,多个操作中有一个执行失败,就会导致整个执行失败。这其实就是基于数据库事物的
ACID特性。
原子性:原子性是事物外观表现的最直接的解释,即要么都执行,要么都不执行。那么是如何实现都不执行或者都执行的?哈
哈这是就是基于mysql的回滚日志(undo log)实现,所有进行修改的操作都会先被记录在这个日志中,当某一个修改操作失败,
就开始读取回滚日志并回复数据。我们这里就简要讨论一下什么是回滚日志。
(1)管理者事物的状态:Active,事物的初始状态,表示事物正在执行。Partially Commited,最后一条语句执行之后
failed,事物无法正常执行。aborted,事物回滚且数据库恢复到事物进行之前的状态
commited:成功执行整个事物。了解事物的运行状态可以理解其中的过程。
(2)并行下事物切割:其实当前多个客户端同时进行才是事物的正正状态。比如A用户正在执行update操作
B用户在A执行之前实现了查询操作,B以为这是查询结果,但在随后的一秒A就行了
修改。B又没有重新查询,这样B之前查询结果就错了。回滚日志可以实现并行状态下
将并行操作切割成多段执行。
持久性:将操作结果保持到数据库中。持久性操作也是基于mysql的重做日志(redo log)重做日志分为内存中日志,一个是磁
盘中的日志。前者易失去,后者具有永久性。
(1)缓存日志的新增:在开启事务的过程中,对数据库中的修改会被记录在缓存日志中。
(2)磁盘日志的新增:在事物提交后,缓存日志修改会被读取到磁盘日志中,并进行数据库修改。
隔离性:数据库中每一个客户端操作都是一个独立操作。一个操作未实现,就不会被另一个操作读取和修改。但是这样就会导
事物的并行的问题。这里就要我们自己去处理事物的隔离级别。
(1)未提交读:A用户在事物提交之前修改了某一个属性值,B用户读取到的就是修改后的值。但是如果A的事物
回滚,B这里显示还是修改的值,这就是脏读。举个例子:A操作这样一个属性:set name="AN"
where id =‘1’ ,此时B执行了 select name where id ='1' 结果就是AN,但是A回滚了name=‘BN’,
B的结果还是AN。
(2)已提交读:只有事物提交后,另一个客户端才能读取到。
(3)可重复读:其他事物读取的数据只能是已提交的事物,但是,如果有其他事物修改该结果,读取的还是该结
果。
(4)串行化:只要有一个事物在执行这个操作,其他都得等着直到该事物执行结束。
上述4中隔离性,性能依次降低,安全性依次升高。那么如何实现高级别的隔离?
方法一:.比较常见的方法就是加锁,my sql和常见数据的锁都分为2中,共享锁(读锁)和互斥锁(写锁),前
者实现了 读操作可以并发执行,后者控制数据库更新不会被其他事物肝脑。
方法二:时间戳,时间戳实现事物的隔离级别时,一般会使用乐观锁。先对数据进行修改,在写回时再去判断当
前值,也就是时间戳是否改变过,如果没有改变过,就写入,否则,生成一个新的时间戳并再次更新数
据,乐观锁其实并不是真正的锁机制,它只是一种思想。
方法三:多版本和快照隔离,也就是mvcc,修改时先执行查询。
一致性:数据库中数据的一致性。
上面谈了事物的4种特性,那么4中特性并不是单独执行的。那么我们来看看这4种特性的协作性。
原子性和持久性的协作:从上面可知,这2中特性依赖于回滚日志和重做日志,统称为事物日志。前者保证对事物的影响操作
可以撤销。后者允许提交的事物可以重做,他俩保证了异常回滚和宕机恢复数据。
隔离性和原子性的协作:mvcc特性。正常读取为了保证性能是不会获取互斥锁的,除非在查询后添加for update获取事务所。
4.普通事物的不足。
在上述的讨论中我们均讨论的是单库,单表的事物。明显在分库甚至分布式的事物就需要另外讨论了。
当我们的业务过大,进行横向扩展和纵向扩展时,需要进行分库和分表的时候,我们就需要保证了分库分表和主库主表的事物
一致。实现理论,就是每一次操作都会记录成一条消息,然后发布给其他表库。
分库的情况下实现的是事物的一致性的方法常用的就是2p式提交。
(2)用一个中间表来记录某一个表的修改情况,如果成功就修改第二个,这时候有人就会问第二个表如果执行失败呢?这个就留给大家自己去想了。
(3)这样可以用中间表去管理多个库表的执行了。
其实看到这里我们就能很明显的看出,实则多段式的提交就是类似于消息通知,一个执行了去通知其他的多个的执行。有兴趣
的可以用mq等中间件实现。mq等中间件的消息通知式的提交也是分布式解决事物的一个方案。
(1)单点故障:比如图中的其他三个库挂掉一个怎么办?
(2)数据延时或者不一致:中间表的实现是被动式的
在上述的的2p式提交中,我们曾说过mq事物声明通知可以作为分布式解决事物的一种方案,但是其还是具有2p是提交的缺点,
并且在分布式的情况下这种缺点被放大。因此,基于此有人提出了分布式事物的事物方案---CAP定理
(1)C一致性:客户端知道一系类操作一定会生效
(2)A可用性:每一个操作都必须可预期的响应结束
(3)P分区容错性:单点故障,认可恢复
在实际应用中,P分区一定是要实现的。因此只能根据业务在A,C中选择一个。
cap理论进过证明适用于分布式系统的,但是他只能在cp和ap中选择一个。在实际身产中A理论一定比C理论要实用。就以上述
的2pc的提交为例我们假设两阶段提交的过程中每一个数据库都具有99.9%的可用性,那么如果两阶段提交涉及到两个数据库,这
个结果就是99.8%。根据系统可用性计算公式,假设每个月43200分钟,99.9%的可用性就是43157分钟, 99.8%的可用性就是
43114分钟,相当于每个月的宕机时间增加了43分钟。明显ap理论的实用性大于cp。
在上面我们描述了ap理论实用性大于cp理论。那么如何实现高可用的a理论?这里产生了一个新的定理:BASE理论,实则是
CAP理论的扩展。其内容为:(1)基本可用(2)软状态(3)最终一致性。期核心就是对CAP中的A,C理论的权衡取舍,最终
实现:我们无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。
(1)2段式提交(2pc)
2pc提交基于xa协议的原理,下图就是实现的方式,他将事物分成2各部分,从而牺牲了部分可用性来换取一致性
其优点:在最大方面保持了事物的强一直,适用于数据强一致性的关键领域
其缺点:过于复杂,不舍用于高并发场景
(2)补尝事物(TCC)
其本质就是补尝机制,即每一个操作都有一个与之对应的确定和撤销操作
其优点:实现起来流程相较于2pc比较简单一些
缺点:数据一致性差一些
(3)本地消息表(异步确保)
这种用该是业界内使用最多的方法了,其核心思想是将分布式事物拆分成本地事物。
具体实现的过程如下:并且消息中间件会定时烧苗消息表,然后处理多个消息表中的不一致的数据
优点:这种方案遵循base理论,即便调用链很长也不会出现性能过低的情况
缺点:表侵入
(4)MQ事物消息
基于某一些第三方的mq是支持事物消息的,比如RocketMQ,支持2pc提交,但是rabbotmaq等不支持
a.第一阶段Prepared消息,会拿到消息的地址。
b.第二阶段执行本地事务,第三阶段通过第一阶段拿到的地址去访问消息,并修改状态。
优点:实现最终一致性
缺点:主流mq不支持,实现难度大。
(5)Sagas事物模型
该事物模型是将一个很长的事物拆分成多个多个短事物,然后将多个短事物统一基于一个事物引擎来实现。当一个短事物
执行失败,前面的已经执行成功的都将执行补偿执行。
如图,当短事物02执行失败,其他全部执行补尝回滚