对于Mysql事务我们都知道事务具有ACID四个特性,分别为:
- 原子性,一组操作不可分割,要么全部成功要么全部失败 。Mysql如何实现原子性,是通过innodb的 undolog回滚日志实现,当事务失败的时候执行回滚操作
- 一致性, 任何写到数据库的数据都必须满足于预先定义的规则(比如余额不能小于0、外键约束等)
- 隔离性,如果两个事务同时操作一条数据,通过加锁,按照顺序执行,不能相互影响
- 持久性。 通过redolog实现 记录的是新数据的备份 用来持久化 , Undolog记录的是旧数据 用来数据的回滚
基于以上四个特性,我们可以总结出事务 多个操作要么一起成功,要么一起失败,事务提交后,进行落盘存储,接下来我们来看一下InnoDB是如何实现事务的
对于Innodb它主要由俩个事务日志文件redoLog和undoLog来保证事务的原子性,一致性,持久性;隔离性由锁来控制 如间隙锁,排它锁;
Redo Log(重做日志):
是什么?
redolog是InnoDB里用来记录事务提交的物理日志文件,记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,主要用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。
通过redolog实现 记录的是新数据的备份 用来持久化
Undolog记录的是旧数据 用来数据的回滚
redo log进行刷盘比对数据页刷盘效率高,具体表现如下
- redo log体积小,毕竟只记录了哪一页修改了啥,因此体积小,刷盘快。
- redo log是一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快。
什么是脏读,幻读,不可重复读?
脏读: 读取到了其他事务未提交的数据
不可重复读: 是指在同一个事务中以相同条件去读取到的数据不同 针对修改
幻读: 一个事务中以相同条件去读取到的数据的条数不同 针对的是插入和删除
Mysql隔离级别:
读未提交:
产生: 脏读 幻读 不可重复读
读提交:
可以解决脏读
产生:幻读 不可重复读
可重复读:
可以: 脏读 幻读 不可重复读
幻读(mysql使用间隙锁实现)
串行化:
可以解决: 脏读 幻读 不可重复读
分布式事务解决方案:
2pc 两段式提交优缺点
一个下订单的操作
订单服务 库存服务 积分服务
一个下请求所涉及到的操作, 也是相当于一组操作,全局事务,而针对于每个单独的服务而言的事务 称之为分支事务
怎么才能够知道哪些分支事务是属于一个全局事务的呢?
Seata处理分布式事务流程:
Xid:全局事务的id
Tc:事务协调器 用来注册全局事务和管理分支事务的状态
TM:全局事务管理器 用来提交或者回滚全局事务
Rm:分支事务管理器
流程:
- 向tc事务协调器注册一个全局事务 生一个全局事务的XID
- 开始执行每个分支事务,但是此时携带了全局事务的xid,每一个分支事务都需要根据这个XID向TC注册分支事务
- 执行每个分支的业务代码,并且写入undolog,然后提交本地事务,并将本地事务的提交状态告知TC
- 全是事务管理器TM,向TC发送全局事务提交的请求,此时从TC获取所有分支事务的状态
- 如果所有分支事务状态提交都是成功的
此时只需要删除每个分支事务的undolog即可,因为分支事务的本地事务已经提交过了
如果分支事务中有失败的,
此时那些成功的分支事务就要根据undolog去回滚