ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

单节点事务与分布式事务

2021-11-02 22:32:56  阅读:133  来源: 互联网

标签:事务 快照 隔离 提交 一致性 数据 节点 分布式


单节点事务

在一个不确定的存储环境中,会有许多出错的情况。例如,网络故障、磁盘故障、应用程序的某种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理论,也就是保证最终一致性,通过牺牲短时间一致性来保证系统可用性。

分布式事务细节有待分析和学习,告一段落。

标签:事务,快照,隔离,提交,一致性,数据,节点,分布式
来源: https://blog.csdn.net/fenglei0415/article/details/121110843

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有