PostgreSQL事务基础理解

PostgreSQL事务

事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。数据库事务通常包含一个序列对数据库的读和写操作,主要是包含以下两个目的:

  • 为数据库操作序列提供一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下保持数据一致性的方法。
  • 多个应用程序并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,保证彼此之间操作的操作互不影响。

当事务提交给数据库管理系统,则数据库管理系统需要确保该事务中的所有操作都成功,并且操作会结果被永久保存在数据库中;如果事务中有部分操作失败,则事务中的所有操作都需要回滚,回到事务执行前的状态;同时,该事务对数据库或者其他事务互不影响,所有的事务都是独立运行。

1、事务的属性

  • 原子性:一个事务中的所有操作要么全部完成,要么一个都不做,不会在中间某个环节结束。
  • 一致性:事务应确保数据库的状态从一个一致状态转变为另一个一致状态,事务执行结束后数据库的完整性没有破坏。
  • 隔离性:数据库允许多个并发事物对数据库中的数据进行读写操作,隔离性可以防止多个事务并发执行时导致的数据不一致性。事务根据隔离等级可以分为4级:读未提交、读已提交、可重复度和串行化。
  • 持久性:事务执行完成后,对数据的修改是永久的

3、事务的使用

在psql中默认开启自动提交事务的功能,每提交一条SQL语句,都会被自动提交。可以通过设置AUTOCOMMIT参数来关闭自动提交功能。

postgres=# \dt		# 当前存在一张test表
        List of relations
 Schema | Name | Type  |  Owner   
--------+------+-------+----------
 public | test | table | postgres
(1 row)

postgres=# \set AUTOCOMMIT off		# 设置AUTOCOMMIT参数关闭
postgres=# \echo :AUTOCOMMIT
off
postgres=# drop table test;		# 删除test表
DROP TABLE
postgres=*# \dt		# 查看是否存在表
Did not find any relations.
postgres=*# rollback ;		# 手动回滚事务
ROLLBACK
postgres=# \dt		# test表恢复到初始状态
        List of relations
 Schema | Name | Type  |  Owner   
--------+------+-------+----------
 public | test | table | postgres
(1 row)
postgres=#

此外还可以通过begin关键字开启事务,通过commit提交事务,还可以通过rollback进行回滚。

这里引入两个关键字beginstart transaction,两者作用是一样的,但是在使用过程中begin可能会成为关键字的时候,采用start transaction可以避免这种情况发生。

postgres=# begin;	# 启动一个事务
BEGIN
postgres=*# insert into test values(1,now());	# 插入一条数据
INSERT 0 1
postgres=*# select count(*) from test;	# 查询数据条目
 count 
-------
   201
(1 row)

postgres=*# rollback ;		# 进行事务回滚
ROLLBACK
postgres=# select count(*) from test;	# 查询数据条目
 count 
-------
   200
(1 row)

PostgreSQL支持保存点的功能,在一个大的事务中,可以把操作过程分为几个部分,每个部分执行成功后可以建一个保存点,若后边的部分执行失败,则会回滚到次保存点,无需回滚整个事务。

postgres=# select * from test;		# 初始表数据条数为空
 id 
----
(0 rows)

postgres=# begin ;		# 开启事务
BEGIN
postgres=*# insert into test values(1);		# 插入一条数据
INSERT 0 1
postgres=*# savepoint test_point_1;		# 建立一个保存点test_point_1
SAVEPOINT
postgres=*# insert into test values(2);
INSERT 0 1
postgres=*# insert into test values(1);		# 由于唯一约束导致插入数据失败
2024-05-18 20:17:47.991 CST [3161] ERROR:  duplicate key value violates unique constraint "test_pkey"
2024-05-18 20:17:47.991 CST [3161] DETAIL:  Key (id)=(1) already exists.
2024-05-18 20:17:47.991 CST [3161] STATEMENT:  insert into test values(1);
ERROR:  duplicate key value violates unique constraint "test_pkey"
DETAIL:  Key (id)=(1) already exists.
postgres=!# rollback to savepoint test_point_1;		# 将事务回滚到test_point_1
ROLLBACK
postgres=*# commit ;
COMMIT
postgres=# select * from test;		# 此时回滚到保存点test_point_1处,数据条目为一条
 id 
----
  1
(1 row)

4、事务的隔离级别

隔离级别描述
读未提交允许事务读取其他事务没有提交的数据,脏读、不可重复读和幻读都会出现
读已提交只允许事务读取其他事务已经提交的数据,可以避免脏读,但是不可重复读和幻读都会出现
可重复读可以保证从一个字段中读取相同的数据,可以任务事务开启时会自动对现有数据进行快照,其他事务修改不管是否提交,当前事务读取的时候快照数据,可以避免脏读和不可重复读,但是幻读问题会出现。
串行化确保事务是串行执行,可以避免所有的并发问题,但是并发效率低,一般不推荐使用

读已提交是PostgreSQL中默认隔离级别。当一个事务处于这个隔离级别是,查询语句只能看到查询开始之前已经提交的数据,无法看到未提交或者查询执行期间其他事务已提交的数据。不过select可以查询自身所在事务中前面尚未提交的操作结果,实际上,select查询看到的时在查询开始运行瞬间的一个快照。

postgres=# begin;
BEGIN
postgres=*# insert into test values(2);
INSERT 0 1
postgres=*# select * from test;  # 查询到当前事务未提交的数据
 id 
----
  1
  2
(2 rows)

postgres=*# rollback ;
ROLLBACK

5、两阶段提交

PostgreSQl数据库支持两阶段提交协议。在分布式系统中,事务包含多台数据库操作,虽然单台数据库可以保证原子性,但是多台数据库之间需要通过两阶段提交来实现。二阶段提交,通过引入一个事务的协调者来管理各个数据库事务的提交和回滚,就是将事务提交分为准备和提交阶段。
具体流程如下:

  • 准备阶段:协调者会给各个参与者发送准备命令。等待所有资源响应之后进入第二阶段。
  • 提交阶段:若第一阶段所有参与者都返回准备成功后, 协调者再次向所有参与者发送提交事务的命令,然后等待所有事务都提交成功后,返回事务执行成功。

在这里插入图片描述

postgres=# select * from test;		# 查询当前表数据条目
 id 
----
  1
  2
(2 rows)

postgres=# begin;	# 开启事务
BEGIN
postgres=*# insert into test values(3);		# 插入数据
INSERT 0 1
postgres=*# prepare transaction 'test_transaction';		# 使用prepare transaction提交事务(第一阶段)
PREPARE TRANSACTION
postgres=# select * from test;		# 查询当前表数据条目
 id 
----
  1
  2
(2 rows)

postgres=# \q
[postgres@pg14 pgdata]$ pg_ctl -D /opt/pgdata restart	# 重启数据库
waiting for server to shut down....2024-05-18 21:03:12.231 CST [4000] LOG:  received fast shutdown request
2024-05-18 21:03:12.234 CST [4000] LOG:  aborting any active transactions
2024-05-18 21:03:12.236 CST [4000] LOG:  background worker "logical replication launcher" (PID 4008) exited with exit code 1
2024-05-18 21:03:12.237 CST [4002] LOG:  shutting down
2024-05-18 21:03:12.791 CST [4000] LOG:  database system is shut down
 done
server stopped
waiting for server to start....2024-05-18 21:03:12.867 CST [4026] LOG:  starting PostgreSQL 14.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
2024-05-18 21:03:12.868 CST [4026] LOG:  listening on IPv6 address "::1", port 5432
2024-05-18 21:03:12.868 CST [4026] LOG:  listening on IPv4 address "127.0.0.1", port 5432
2024-05-18 21:03:12.873 CST [4026] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5432"
2024-05-18 21:03:12.884 CST [4027] LOG:  database system was shut down at 2024-05-18 21:03:12 CST
2024-05-18 21:03:12.888 CST [4027] LOG:  recovering prepared transaction 869 from shared memory
2024-05-18 21:03:12.893 CST [4026] LOG:  database system is ready to accept connections
 done
server started
[postgres@pg14 pgdata]$ psql
psql (14.6)
Type "help" for help.

postgres=# select * from test;		# 查询当前表数据条目
 id 
----
  1
  2
(2 rows)

postgres=# commit prepared 'test_transaction';	# 提交二阶段事务
COMMIT PREPARED
postgres=# select * from test;		# 查询当前表数据条目,事务被提交,可以查询到插入数据
 id 
----
  1
  2
  3
(3 rows)

test_transaction是作为两阶段提交中全局事务ID,由事务协调器生成,一旦执行一阶段提交事务,则会把事务持久化,即使数据库重启也不会影响事务的回滚。

两阶段提交是一种尽量保证强一致性的分布式事务,因此它是同步阻塞的,而同步阻塞就导致长久的资源锁定问题,总体而言效率低,并且存在单点故障问题,在极端条件下会存在数据不一致的风险。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1.Redis之初识Redis分布式系统

1.初识Redis 1.1 官网 Redis中文网 Redis 教程 | 菜鸟教程 (runoob.com) 1.2 解释 在内存中存储数据 定义变量,不就是在内存中存储数据嘛?? Redis 是在分布式系统(进程的隔离性:Redis 就是基于网络,可以把自己内存中的变量给别的进程…

【Linux】简单模拟C语言文件标准库FILE

👦个人主页:Weraphael ✍🏻作者简介:目前正在学习c和算法 ✈️专栏:Linux 🐋 希望大家多多支持,咱一起进步!😁 如果文章有啥瑕疵,希望大佬指点一二 如果文章对…

Java进阶学习笔记10——子类构造器

子类构造器的特点: 子类的全部构造器,都会先调用父类的构造器,再执行自己。 子类会继承父类的数据,可能还会使用父类的数据。所以,子类初始化之前,一定先要完成父类数据的初始化,原因在于&…

【Java面试】一、Redis篇(上)

文章目录 0、准备1、缓存穿透:不存在的key2、缓存击穿:热点key过期3、缓存雪崩:大批key同时过期4、双写一致性4.1 要求高一致性4.2 允许一定的一致延迟 5、面试 0、准备 Redis相关概览: 以简历上所列的项目为切入点,展…

C语言/数据结构——队列的实现

一.前言 今天我们来聊一聊数据结构的一部分——队列。今天我们主要涉及队列的基本概念结构,以及队列的基本实现。 二.正文 1.1队列 1.12队列的概念及结构 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表&#xf…

ue5 中ps使用记录贴

一、快捷键记录 放大图形 ctrlalt空格 放大图形 缩小视口 ctrl空格 ctrlD 取消选区 ctrlt缩小文字 w魔棒工具 选择魔棒的时候把容差打开的多一点 二、案例 移动文字 在相应的图层选择 移动文字 修改图片里的颜色 在通道里拷贝红色通道,复制红色通道粘贴给正常图…

【ELK日志收集过程】

文章目录 为什么要使用ELK收集日志ELK具体应用场景ELK日志收集的流程 为什么要使用ELK收集日志 使用 ELK(Elasticsearch, Logstash, Kibana)进行日志收集和分析有多种原因。ELK 堆栈提供了强大、灵活且可扩展的工具集,能够满足现代 IT 系统对…

CIM模型

CIM 是 Esri 制图信息模型。 它是一个地图内容规范,用于记录在保存、读取、引用或打开时如何永久保留描述不同项目组件的信息。 该规范以 JSON 表示,适用于 ArcGIS 应用程序和 API 中的地图、场景、布局、图层、符号和样式。 CIM 不仅限于制图设置。 要了解属性的组织方式以及…

使用vue3实现右侧瀑布流滑动时左侧菜单的固定与取消固定

实现效果 实现方法 下面展示的为关键代码,想要查看完整流程及代码可参考https://blog.csdn.net/weixin_43312391/article/details/139197550 isMenuBarFixed为控制左侧菜单是否固定的参数 // 监听滚动事件 const handleScroll () > {const scrollTopThreshol…

数据库系统基础知识

一、基本概念 二、数据库三级模式两级映像 三、数据库的分析与设计过程 四、数据模型 五、关系代数 六、数据库完整性约束 七、关系型数据库SQL简介 八、关系数据库的规范化 九、数据库的控制功能 十、数据仓库与数据挖掘基础 十一、大数据基本概念 数据库基本概念 1、数据库…

Spring 对于事务上的应用的详细说明

1. Spring 对于事务上的应用的详细说明 文章目录 1. Spring 对于事务上的应用的详细说明每博一文案2. 事务概述3. 引入事务场景3.1 第一步:准备数据库表3.2 第二步:创建包结构3.3 第三步:准备对应数据库映射的 Bean 类3.4 第四步:…

hcia datacom学习(10):交换机基础

1.二层交换机工作原理 1.1交换机的5种行为 查看mac地址表的命令为 dis mac-address *一个MAC只能关联在一个接口上,一个接口上可以学习多个MAC *mac地址漂移:mac表中,mac地址的出接口从一个端口变为另一个端口的现象。 造成mac漂移的原因…

操作系统实验四 (综合实验)设计简单的Shell程序

前言 因为是一年前的实验,很多细节还有知识点我都已经遗忘了,但我还是尽可能地把各个细节讲清楚,请见谅。 1.实验目的 综合利用进程控制的相关知识,结合对shell功能的和进程间通信手段的认知,编写简易shell程序&…

轻松拿捏C语言——【字符函数】字符分类函数、字符转换函数

🥰欢迎关注 轻松拿捏C语言系列,来和 小哇 一起进步!✊ 🌈感谢大家的阅读、点赞、收藏和关注💕 🌹如有问题,欢迎指正 感谢 目录👑 一、字符分类函数🌙 二、字符转换函数…

Spring MVC/Web

1.Spring MVC 的介绍 Spring Web MVC是基于Servlet API构建的原始Web框架,也是Spring框架的一部分。它提供了灵活可扩展的MVC架构,方便开发者构建高性能的Web应用程序,并与 Spring 生态系统无缝集成。 2.MVC 设计模式 MVC(Model…

【游戏引擎】Unity脚本基础 开启游戏开发之旅

持续更新。。。。。。。。。。。。。。。 【游戏引擎】Unity脚本基础 Unity脚本基础C#语言简介C#基础 Unity脚本基础创建和附加脚本MonoBehaviour生命周期生命周期方法 示例脚本 Unity特有的API常用Unity API 实践示例:制作一个简单的移动脚本步骤1:创建…

SpringCloud系列(30)--准备使用Hystrix的前期工作,创建服务消费者模块

前言:在上一章节中我们创建了服务提供者模块,而本节内容则是创建服务消费者模块。 1、创建一个服务提供者模块,命名为cloud-consumer-feign-hystrix-order80 (1)在父工程下新建模块 (2)选择模块的项目类型为Maven并选择模块要使用的JDK版本 …

Ansible自动化运维中的Setup收集模块应用详解

作者主页:点击! Ansible专栏:点击! 创作时间:2024年5月22日13点14分 💯趣站推荐💯 前些天发现了一个巨牛的🤖人工智能学习网站,通俗易懂,风趣幽默&#xf…

分享:怎么才能保证大数据查询的准确性?

随着大数据应用到金融风控领域,大数据越来越重要了,很多朋友在查大数据的时候都会遇到一个问题,那就是自己查询的大数据什么信息都没有,要么就是很少,这是什么原因呢?要怎么才能保证大数据查询的准确性呢?下面小编就…

WordPress搭建流程

1. 简介 WordPress 是一个 PHP 编写的网站制作平台。WordPress 本身免费,并且拥有众多的主题可以使用,适合用于搭建个人博客、公司官网、独立站等。 2. 环境准备 2.1 WordPress 下载 WordPress 可以在 Worpress中文官网 下载(如果后续要将后台调成中文的话,一定要从中文…