事务

2021-05-30  本文已影响0人  知而乐者

知识点总结

本地事务怎么实现

数据库的一致性:事务开始和结束之间的中间状态不会被其他事务看到,比如多个线程并发执行转账业务:A转给B一块钱,无论成功与否(A+B)的总额是不会变的。

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

不同的加锁方式产生了不同的隔离级别

可串行化:最高的隔离级别,对所有读写的数据都加上读,写、范围锁,性能最差

可重复读:对涉及到的数据加读锁和写锁但是不加范围锁,会有幻读问题,比如查询年龄大于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

上一篇 下一篇

猜你喜欢

热点阅读