PostgreSQL-分布式事务之两阶段提交

news2025/1/21 20:28:57

什么是ACID

在日常操作中,对于一组相关操作,通常需要其全部成功或全部失败。

在关系型数据库中,将这组相关操作称为“事务”。

在一个事务中,多个插入、修改、删除操作要么全部成功,要么全部失败,这称为“原子性”,实际上一个事务还需要有其他三个特性,即“一致性”“隔离性”“持久性”,英文简称为“ACID”:

  • 原子性(Atomicity):事务必须以一个整体单元的形式进行工作,对于其数据的修改,要么全部执行,要么全都不执行。如果只执行事务中多个操作的前半部分就出现错误,那么必须回滚所有的操作,让数据在逻辑上回滚到原先的状态
  • 一致性(Consistency):在事务完成时,必须使所有的数据都保持在一致状态
  • 隔离性(Isolation):事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务是不会查看中间状态的数据的
  • 持久性(Durability):事务完成之后,它对于系统的影响是永久性的,即使今后出现致命的系统故障(如机器重启、断电),数据也将一直保持

在PG中,可以使用多版本并发控制(MVCC)来维护数据的一致性。相比于锁定模型,其主要优点是在MVCC下对检索(读)数据的锁请求与写数据的锁请求不冲突,读不会阻塞写,而写也不会阻塞读

在PG中提供了表和行级别的锁定语句,让应用能更方便地操作并发数据。

DDL事务

在PG中,与其他数据库最大的不同是,大多数DDL也是可以包含在一个事务中的,而且也是可以回滚的。该功能非常适合把PG作为Sharding的分布式数据系统的底层数据库。

比如在Sharding中常常需要在多个节点中建相同的表,此时可以考虑把建表语句放在同一个事务中,这样就可以在各个节点上先启动一个事务,然后再执行建表语句,如果某个节点执行失败,也可以回滚前面已执行建表成功的操作,自然就不会出现部分节点建表成功,部分节点建表失败的情况。

事务的使用方法

手动设置

set AUTOCOMMIT off

image

BEGIN语句

image

SAVEPOINT

PG支持保存点(SAVEPOINT)的功能,在一个大事务中,可以把操作过程分为几个部分,第一个部分执行成功后可以建一个保存点,若后面的部分执行失败,则回滚到此保存点,而不必回滚整个事务。

image

事务隔离级别

数据库的事务隔离级别有以下4种(不同的数据库可能不同):

  • READ UNCOMMITTED:读未提交
  • READ COMMITTED:读已提交
  • REPEATABLE READ:重复读
  • SERIALIZABLE:串行化

对于并发事务,我们不希望发生不一致的情况,这类情况的级别从高到低排序如下:

  • 脏读:一个事务读取了另一个未提交事务写入的数据。这是我们最不希望发生的,因为如果发生了脏读,则在并发控制上,应用程序会变得很复杂
  • 不可重复读:指一个事务重新读取前面读取过的数据时,发现该数据已经被另一个已提交事务修改了。在大多数情况下,这还是可以接受的,只是在少数情况下会出现问题
  • 幻读:一个事务开始后,需要根据数据库中现有的数据做一些更新,于是重新执行一个查询,返回一套符合查询条件的行,这时发现这些行因为其他最近提交的事务而发生了改变,此时现有的事务如果再进行下去的话,就可能会导致数据在逻辑上的一些错误。

不同事务隔离级别下的行为:

  1. 读未提交:脏读、不可重复读、幻读
  2. 读已提交:不可重复读、幻读
  3. 重复读:幻读
  4. 可串行化:不会发生以上行为

对幻读理解不清楚的,可以参考以下实例

幻读实例

数据准备

image

开启事务更新数据

image
更新操作执行完之后,新开启一个事务插入一条数据
image

更新操作事务提交后,发现有一条数据id=4未更新,像产生了幻觉一样,这就是幻读

PG事务隔离级别

  • 9.1版本之前只有读已提交和可串行化
  • 9.1版本之后增加了重复读

也就是说在PG中,如果你选择了读未提交的级别,实际上还是读已提交;如果选择可重复读级别,有可能实际上仍是可串行化。

PG中默认的隔离级别是读已提交。当一个事务运行于这个隔离级别时,执行SELECT查询(没有FOR UPDATE/SHARE子句)只能看到查询开始之前已提交的数据,而无法看到未提交或者查询期间其他事务已提交的数据;可以看到自身所在事务前面尚未提交的更新结果。实际上,SELECT查询看到的是查询开始运行瞬间的一个快照。

注意:同一个事务中两个相邻的SELECT命令可能看到不同的快照,因为可能有其他事务在第一个SELECT执行完之后,提交了更新结果

两阶段提交

PG数据库支持两阶段提交协议

在分布式系统中,事务中往往包含了多台数据库上的操作,虽然单台数据库的操作能够保证原子性,但多台数据库之间的原子性就需要通过两阶段提交来实现了,两阶段提交是实现分布式事务的关键

两阶段提交有如下5个步骤:

  1. 应用程序先调用各台数据库做一些操作,但不提交事务。然后应用程序调用事务协调器(该协调器可能也是由应用自己实现的)中的提交方法
  2. 事务协调器将联络事务中涉及的每台数据库,并通知它们准备提交事务,这是第一阶段的开始。PG中一般是调用PREPARE TRANSACTION命令
  3. 各台数据库接收到PREPARE TRANSACTION命令后,如果要返回成功,则数据库必须将自己置于如下状态:确保后续能在被要求提交(回滚)事务的时候提交(回滚)事务,所以PG会将已准备好提交的信息写入持久存储区中。如果数据库无法完成此事务,它会直接返回失败给事务协调器
  4. 事务协调器接收所有数据库的响应
  5. 在第二阶段,如果任何一个数据库在第一阶段返回失败,则事务协调器将会发一个回滚命令ROLLBACK PREPARED给各台数据库。如果所有数据库的响应都是成功的,则向各台数据库发送COMMIT PREPARED命令,通知各台数据库事务成功

两阶段提交实例

配置max_prepared_transactions

image
image

重启服务

image

二阶段提交

image

  • 第一阶段:PREPARE TRANSACTION ‘osdba_global_trans_0001’
  • 第二阶段:COMMIT PREPARED ‘osdba_global_trans_0001’

注意:第一阶段结束后,重启服务,模拟数据库宕机。服务重启后,第二阶段提交,数据可以正常查询。

上述命令osdba_global_trans_0001是两阶段提交中全局事务的ID,由事务协调器生成(事务协调器会持久化该ID)。PG数据库一旦成功执行这条命令,也会把事务持久化,即使数据库重启,此事务也不会回滚或丢失

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/522344.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringCloud Nacos 注册配置中心

前言 在微服务架构中,注册中心是核心的基础服务之一。相信不少同学都用过 Dubbo 这个流行分布式框架,很久之前微服务还没这么盛行,Dubbo就提供了比较完善的服务治理功能,而服务治理的实现主要依靠的就是注册中心。 许多同学接触…

Apache Kafka - 生产者内存优化注意事项

文章目录 1. 调优内存池参数2. 限制客户端生产速率3. 减小单条消息大小4. 监控生产者内存和性能5. 评估topic的partition分布6. 增加更多生产者实例7. Kafka升级和更强劲的硬件小结 1. 调优内存池参数 增大batchSize和linger ms,适当延长消息在内存池的最大延迟,减少发送次数。…

【C++初阶】第十二篇:priority_queue的使用与模拟实现

文章目录 priority_queue的使用priority_queue的介绍priority_queue的定义方式priority_queue各个接口的使用 仿函数代码样例使用场景(示例) priority_queue的模拟实现堆的向上调整算法堆的向下调整算法priority_queue的模拟实现 总结 priority_queue的使…

redis:基于 Streams 的消息队列

前言 Redis 5.0 及 5.0 以后的版本提供的Streams 是专门为消息队列设计的数据类型,它提供了丰富的消息队列操作命令。 消息队列 Streams 操作 XADD:插入消息,保证有序,可以自动生成全局唯一 ID; 名称为 mqstream 的…

【第七章:输入输出系统】

目录 知识框架No.0 引言No.1 输入输出系统一、基本概念二、I/O控制方式1、主机如何与I/O设备进行交互?2、CPU是如何通过I/O接口与外设交互的3、如何判断读入的数据有没有被输入完成呢?4、对于快速I/o设备,如“磁盘”,每准备好一个字就给CPu发…

【C语言】操作符详解(下)

操作符详解 1.条件操作符2. 逗号表达式3.下标引用,函数调用和结构体成员4.表达式求值4.1隐式类型转换4.2算术转换 5.操作符的属性 所属专栏:C语言 博主首页:初阳785 代码托管:chuyang785 感谢大家的支持,您的点赞和关注…

原生js手动实现一个多级树状菜单效果(高度可过渡变化) + 模拟el-menu组件实现(简单版)

文章目录 学习链接效果图代码要点 简单模拟el-menu实现TestTree.vueMenu.vueSubMenu.vue 学习链接 vue实现折叠展开收缩动画 - 自己的链接 elment-ui/plus不定高度容器收缩折叠动画组件 - 自己的链接 Vue transition 折叠类动画自动获取隐藏层高度以及手风琴效果实现 vue t…

Sqoop: Hadoop数据传输的利器【Sqoop实战】【上进小菜猪大数据系列】

我是上进小菜猪,沈工大软件工程专业,爱好敲代码,持续输出干货,欢迎关注。 Sqoop: Hadoop数据传输的利器, 在大数据领域,数据的传输和集成是至关重要的任务之一。Sqoop(SQL to Hadoop)作为Apache…

ChatGPT的前世今生,到如今AI领域的竞争格局,本文带你一路回看!

73年前,“机器思维”的概念第一次被计算机科学之父艾伦图灵(Alan Turing)提出,从此,通过图灵测试成为了人类在AI领域为之奋斗的里程碑目标。 73年后的今天,在AI历经了数十年的不断进化、迭代后&#xff0c…

【第二章:数据的表示和运算】

目录 知识框架No.0 引言No.1 数制与编码一、进位计数制及其相互转换二、BCD码三、无符号的整数在计算机内部表示和运算1、表示2、加法、减法实现 四、带符号的整数在计算机内部表示和运算1、表示1.1、原码表示1.2、原码形式实现加减法运算不行1.3 补码表示1.4 补码实现加法运算…

分享一个图片展示特效

先上效果图&#xff1a; 备注&#xff1a;这个效果图太大了&#xff0c;压缩了一下效果有点不咋好看。感兴趣同学们可以自己运行代码看一下&#xff0c;保证不会失望~ 再上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta cha…

mysql数据库的表操作 --3

表操作 3.1&#xff1a;创建表 语法&#xff1a; CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎; 说明&#xff1a; field 表示列名 datatype 表示列的…

Java 数组与List转换

int[] 与 List<Integer> 转换 刷题常见 int[] 转 List<Integer> // int[] 转 List<Integer> int[] arr {1, 2, 3, 4, 5}; List<Integer> list Arrays.stream(arr).boxed().collect(Collectors.toList());解释&#xff1a; Arrays.stream(arr) /…

基于Ant DesignPro Vue + SpringBoot 前后端分离 - 部署后解决跨域的问题

基于Ant DesignPro Vue SpringBoot 前后端分离 - 部署后解决跨域的问题 通过Ant DesignPro Vue SpringBoot 搭建的后台管理系统后&#xff0c;实现了前后端分离&#xff0c;并实现了登录认证&#xff0c;认证成功后返回该用户相应权限范围内可见的菜单&#xff1b;但时将服务…

剑指 Offer II 105. 岛屿的最大面积代码注释

题目&#xff1a; 给定一个由 0 和 1 组成的非空二维数组 grid &#xff0c;用来表示海洋岛屿地图。 一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合&#xff0c;这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0&#xff08;代表…

第一章 集合框架

文章目录 什么是集合框架集合接口Set和List的区别 集合实现类&#xff08;集合类&#xff09;集合算法 什么是集合框架 官方教程 Java 集合框架 Java Collection Framework &#xff0c;又被称为容器container&#xff0c;是定义在java.util包下的一组接口 interfaces和其实现…

【华为HCIP | 高级网络工程师】刷题日记(8)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生 &#x1f43b;‍❄️个人主页&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;落798. &#x1f54a;️系列专栏&#xff1a;零基础学java ----- 重识c语言 ---- 计算机网络 &#x1f413;每日一…

68.建立手风琴组件第一部分

本节目标 使用的文件 本次使用的文件可私信我获取&#xff0c;本次就只有两张图片 ● 我们导入两个照片至我们的项目文件夹&#xff0c;并新建一个HTML文件 ● 之后我们输入感叹号&#xff0c;让他自动为什么生成初始代码 ● 之后我们修改下title&#xff0c;导入字体、…

springboot+vue家具网站(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的家具网站。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风歌&#…

kafka之消费者进阶

一、几个概念 1. 消费者组 消费者组&#xff1a;一个消费者组包含多个消费者。同一个消费组的消费者&#xff0c;分别消费不同的partition&#xff0c;便于加快消费。 kafka约定在一个消费者组中&#xff0c;对于同一个topic&#xff0c;每个consumer会分配不同partition&am…