知识点总结
本地事务怎么实现
- 原子性、隔离性和持久性都是要达到一致性的目的
数据库的一致性:事务开始和结束之间的中间状态不会被其他事务看到,比如多个线程并发执行转账业务:A转给B一块钱,无论成功与否(A+B)的总额是不会变的。
- 现在已经不限于数据库要保证一致性,缓存,消息,队列,等都会涉及到事务处理
- 同一个数据源通过A、I、D获得一致性相对容易,但是单个服务多个数据源,多个服务多个数据源就需要涉及到架构问题
- ARIES理论,主流的数据库事务的实现都受其影响
- 单数据源通过Commit Logging的方式来实现原子性和持久性(阿里的OceanBase就是这样实现的)
如果在操作过程中直接将某行改为某个值那么奔溃后就不能在恢复,CommitLogging的实现方式是通过将修改数据的全部信息(比如修改了什么数据,数据物理上的哪个内存页中)以顺序追加日志的方式写入(这是最高效的写入方式)先记录到磁盘中,只有在日志记录全部都安全落盘,见到代表事务成功提交的Commit Record后数据库才会根据日志上的信息进行真正数据上的修改,修改完成后在日志加入一条End Record表示已经完成持久化(RedoLog)
CommitLogging有一个巨大的缺陷,对数据的真实修改必须发生在事务提交,日志写入CommitRecord之后即使有冲入的IO也无法利用
ARIES提出了“Write-Ahead Logging”的日志改进方案,Write-Ahead就是允许在事务提交之前提前写入变动的数据
Write-Ahead Logging先将何时写入变动数据,按照事务的提交时点为界,分为了FORCE和STEAL两类:
FORCE,当事务提交后,要求变动数据必须完成写入成为FORCE,如果不要求强制写入则成为NO-FORCE,绝大多数数据库都是NO-FORCE策略
STEAL,事务提交之前允许事务的提前写入称为STEAL,不允许则称为NO-STEAL,允许数据提前写入有利于利用空闲的I/O资源,也利于节省数据库缓存区内存
Commit Logging允许NO-FORCE,但是不允许STEAL
FORCE实现不了原子性的
Write-Ahead Logging允许NO-FORCE也允许STEAL,解决方法就是增加Undo Log的日志,当数据写入磁盘前必须记录Undo Log,写明修改了哪个位置的数据,从什么值修改为什么值
image.png
- 单数据源实现原子性和持久性的方式还有ShadowPaging(影子分页,复制一份数据再进行修改)
- 单数据源实现隔离性是通过锁来实现的(产生四种隔离级别)
不同的加锁方式产生了不同的隔离级别
可串行化:最高的隔离级别,对所有读写的数据都加上读,写、范围锁,性能最差
可重复读:对涉及到的数据加读锁和写锁但是不加范围锁,会有幻读问题,比如查询年龄大于10的人数查到有10人,之后另一个事务插入一条,就会查到有11个人(ARIES理论来进行的讨论,实际的Mysql没有幻读问题)
读已提交:对事务涉及到的数据加写锁,读锁用完后马上释放,会有不可重复读的问题,两次查询过程中可能有不同的结果
读未提交:对涉及到的数据只加写锁,完全不加读锁,会有脏读问题,为什么会有脏读问题,因为写锁是禁止其他事务增加读锁,而不是禁止事务读取数据
MVCC是一种读取优化策略,针对一个事务读+一个事务写场景,只有在可重复读和读已提交的场景才会涉及到MVCC来优化(其他两个场景也不加读锁),MVCC就是在数据库每一行增加两个看不见的字段,CREATE_VERSION和DELETE_VERSION
数据插入:CREATE_VERSION记录插入的事务ID,DELETE_VERSION为空
数据删除:CREATE_VERSION为空,DELETE_VERSION删除事务的ID
数据修改:将原来的数据复制一份,原数据DELETE_VERSION记录修改的事务ID,CREATE_VERSION为空,复制出来的CREATE_VERSION记录插入的事务ID,DELETE_VERSION为空
每一行还有一个指向undo.log的指针,undo.log是一个链表的数据结构存储,多个事务进行修改后就会产生链表(比如一个事务在读这行数据,读完之后事务没有提交,之后有多个事务执行都修改了这行记录,undo.log就有多个节点,什么时候清除?(在最小的事务ID提交之后吗?))
image.png
单服务多数据源的实现
XA协议、2PC、3PC
XA:一个事物管理器接口和满足XA规范的定义接口
2PC协议来实现XA:连个阶段,准备阶段和提交阶段,准备阶段就是暂时不写入最后一条Commit Record,提交阶段会发送commit,如果任何一个参与者回复NO-Prepared或者超时,则在发送
Abort指令
3PC协议来实现XA:CanCommit、PreCommit和DoCommit三个阶段
跨系统的分布式事务
消息队列、TCC和SAGA
网友评论