单节点事务与分布式事务
2021/11/2 23:15:09
本文主要是介绍单节点事务与分布式事务,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
单节点事务
在一个不确定的存储环境中,会有许多出错的情况。例如,网络故障、磁盘故障、应用程序的某种bug,这些未解决的问题都会影响到系统的高可靠性。处理好上述问题就需要完善的容错机制,而事务就是一直以来简化这些问题的首选。
事务提供的安全保障即ACID,分别代表原子性、一致性、隔离性与持久性。其中,A、I、D属于数据库系统固有属性,一致性更多是应用层属性,应用层借助数据库提供的原子性和隔离性来实现一致性,一致性本身并不源于数据库。
1. 原子性
原子性能够保证,当事务进行中发生了错误,就必须中止事务,并将部分完成的写入全部丢弃。正因为如此,事务可以安全地重试。
2. 一致性
ACID中的一致性主要是指对数据有特定的预期状态,任何数据更改必须满足这些状态的约束。
3. 隔离性
事务隔离性意味着多个事务相互隔离,它们不能互相交叉。最强的隔离性就是串行,其次是快照隔离。
4. 持久性
持久性承诺,一旦事务提交成功,即使存在硬件故障或数据库崩溃,事务所写入的任何数据都不会丢失。写入过程中,还涉及WAL,而对于支持远程复制的数据库,持久性则意味着数据已成功复制到多个节点。
但是:
如果两个事务操作的是不同的数据,即不存在数据依赖关系,则它们可以安全地并行执行。只有当出现某个事务修改数据而另一个事务同时要读取该数据,或者两个事务都要同时修改相同的数据时,才会引发一系列不安全问题。
可串行化的隔离会严重影响性能,而许多数据库却不能牺牲性能,所以就倾向于采用较弱的隔离级别。如下:
1. 读-未提交
只能防止脏写,不能防止脏读。暂时还没发现有数据库采用这种隔离级别,因为太弱了,读的准确性都保障不了。
2. 读-提交
- 防止脏读(读时,只能看到已成功提交的数据):比如事务需要更新多个对象,脏读意味着另一个事务可能会读到部分更新,而非全部。
- 防止脏写(写时,只会覆盖已成功提交的数据):防止多事务并发写问题。
- 实现:加行锁防止脏写。维护旧值快照防脏读,事务提交成功,才会切换到新值。
3. 可重复读
可重复读指一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。而读提交无法保证可重复读。
比如:在复制的场景中,拿Redis举例,主线程在做RDB时采用COW技术,就是写时复制。简单讲,主线程开始执行RDB快照时,要保证数据是不会更改的,才有可能完成一份完整的快照,那后续的写请求是另起一块内存进行操作。假设,在做快照的同时,内存发生了更改,这样生成的快照发送给其他节点,就会导致永久的不一致性。
方案就是通过多版本并发控制(MVCC)生成一份快照,所有的事务都是在不同版本的快照中执行,通过这样的方式来解决不可重读读问题。同时在实际中,读提交的脏读也是由MVCC来解决(保留两个版本)。
4. 更新丢失
场景:两个事务同时执行读-修改-写入操作,出现其中一个覆盖了另一个的写入,但又没包含对方最新值,最终导致了部分修改数据发生了丢失。快照隔离的一些实现可以自动防止这种异常。
5. 写倾斜与幻读
写倾斜的现象导致出现了幻读。什么是写倾斜?
如果两个事务读取相同的一组对象,然后更新一部分。不同的事务更新不同的对象,就可能会发生写倾斜。
而不同的事务更新的是同一个对象,则可能发生脏写或更新丢失。
举个例子:两个前台小姐姐都想要请假,请假的要求是如果其中一位已申请,另一位只能等待。她们两位都去OA上查看,发现对方没有申请记录。便在同一时刻点了自己的请假申请,而且事务提交成功。所以OA上显示两位都请假成功。
这种情况发生的原因是事务首先要查询数据,根据数据结果来做出决定。然而当事务提交时,该数据已经被另一事务做了修改,不符合了提交的情况,但最终还是提交成功。
这种在一个事务中的写入改变了另一个事务查询结果的现象,成为幻读。快照只能解决只读查询时的幻读,无法解决写事务时出现的写倾斜现象。
解决方案:
- 串行执行。如果利用Redis这种高性能的内存数据库,有时会比并发的系统效率更高。
- 两阶段加锁(2PL)。谓词锁、共享锁、索引区间锁...... 这种也被成为悲观并发控制机制,如果执行期间可能出错,那直接放弃,采用等待方式保证安全。但是性能太差,很少有数据库使用。
- 可串行化的快照隔离(SSI)。相反,这种设计就是乐观并发控制,寄希望于无事,如果执行完发现了冲突就会中止事务重试。相对2PL,性能会高很多。因为执行前是不加锁的。
分布式事务
对于跨节点或跨分区的事务的数据库,会面临一种问题:某个事务可能在一些节点执行成功,但在其他节点却因为某些故障失败。为了维护原子性,所有节点必须对事务的结果达成一致,要么全部成功提交,要么全部中止并回滚。也就是所有节点要对这一问题达成共识。
常用的实现算法就是两阶段提交(2PC)和三阶段提交(3PC),都属于强一致性。在大数据领域,很多引擎为了高性能并不要求强一致性,而是更倾向于BASE理论,也就是保证最终一致性,通过牺牲短时间一致性来保证系统可用性。
分布式事务细节有待分析和学习,告一段落。
这篇关于单节点事务与分布式事务的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26Mybatis官方生成器资料详解与应用教程
- 2024-11-26Mybatis一级缓存资料详解与实战教程
- 2024-11-26Mybatis一级缓存资料详解:新手快速入门
- 2024-11-26SpringBoot3+JDK17搭建后端资料详尽教程
- 2024-11-26Springboot单体架构搭建资料:新手入门教程
- 2024-11-26Springboot单体架构搭建资料详解与实战教程
- 2024-11-26Springboot框架资料:新手入门教程
- 2024-11-26Springboot企业级开发资料入门教程
- 2024-11-26SpringBoot企业级开发资料详解与实战教程
- 2024-11-26Springboot微服务资料:新手入门全攻略