【7】PostgreSQL 事务

【7】PostgreSQL 事务

  • 前言
  • 使用事务
  • 事务内错误处理
  • 事务保存点
  • DDL 事务

前言

PostgreSQL 中,每一个操作都是一个事务。即使一个简单的查询(select),这也是一个事务。
例如:

postgres=# select now();now              
-------------------------------2025-07-07 09:08:11.218095+08
(1 row)postgres=# 

上述的 select 语句将是一个单独的事物。

使用事务

PostgreSQL 中,如果想要让多个语句作为同一个事务的一部分,需使用 begin 子句。

begin 语法如下:

postgres=# \h begin;
Command:     BEGIN
Description: start a transaction block
Syntax:
BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]where transaction_mode is one of:ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }READ WRITE | READ ONLY[ NOT ] DEFERRABLE
postgres=# 

begin 子句将多个 SQL 命令包装到一个事务中,示例:

postgres=# begin;
BEGIN
postgres=# 
postgres=# select now();now              
-------------------------------2025-07-07 09:15:03.335124+08
(1 row)postgres=#   ### 这里等待了好多秒,
postgres=#   ### 再次执行 select now() 查询的时间一致。
postgres=#
postgres=# select now();now              
-------------------------------2025-07-07 09:15:03.335124+08
(1 row)postgres=# 

上述的 begin 语句示例中,需要注意两次 select 查询之间其实等待了好多秒(即:第一个 select 查询后,等待好多秒后,再次执行第二个 select 语句)。

在同一个事务中,两次 select 查询之间即使等待好多秒,两次查询结果也是一致的

commit 语法如下:
要结束一个事务,可使用 commit 语句

postgres=# \h commit
Command:     COMMIT
Description: commit the current transaction
Syntax:
COMMIT [ WORK | TRANSACTION ]postgres=# 

commit 子句提交一个事务:

postgres=# commit;
COMMIT
postgres=# 

另外,在 PostgreSQL 中除了使用 commit 语句提交事务外,还可使用 end 语句。

end 语法如下:

postgres=# \h end;
Command:     END
Description: commit the current transaction
Syntax:
END [ WORK | TRANSACTION ]postgres=# 
postgres=# 
postgres=# ### 和 commit 子句做一个对比,语法是一样的。
postgres=# \h commit;
Command:     COMMIT
Description: commit the current transaction
Syntax:
COMMIT [ WORK | TRANSACTION ]postgres=# 

提交(commit | end) 对应的命令,有个 rollback

rollback 语法如下:

postgres=# \h rollback;
Command:     ROLLBACK
Description: abort the current transaction
Syntax:
ROLLBACK [ WORK | TRANSACTION ]postgres=# 

注意

  • rollback 并不是成功的结束一个事务,仅会停止事务 而不把事务中的部分对其他事务可见。【见描述:abort the current transaction
  • rollback 含义相同的还有一个 abort 语句

abort 语法如下:

postgres=# \h abort
Command:     ABORT
Description: abort the current transaction
Syntax:
ABORT [ WORK | TRANSACTION ]postgres=# 

事务内错误处理

PostgreSQL 中,只有 没有发生错误的事务 才能被提交

如下示例
访问一个不存在的函数 non_existent_function() 故意制作报错,查看数据库表现。

postgres=# CREATE TABLE tb_test (
postgres(#     id INT
postgres(# );
CREATE TABLE
postgres=# 
postgres=# begin;
BEGIN
postgres=# insert into tb_test(id) values(1001);
INSERT 0 1
postgres=# 
postgres=# select * from tb_test;id  
------1001
(1 row)
postgres=# 
postgres=#  ### 这里访问一个不存在的函数,故意制作报错。
postgres=# SELECT non_existent_function();
ERROR:  function non_existent_function() does not exist
LINE 1: SELECT non_existent_function();^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
postgres=# 
postgres=# 
postgres=# select * from tb_test;
ERROR:  current transaction is aborted, commands ignored until end of transaction block
postgres=# 
postgres=# commit;
ROLLBACK
postgres=# 
postgres=# select * from tb_test;id 
----
(0 rows)postgres=# 

上述同样的操作步骤,看下 在 MySQL 中的表现

MySQL 数据库版本:

[root@localhost][testdb]> select version();
+------------+
| version()  |
+------------+
| 5.7.26-log |
+------------+
1 row in set (0.00 sec)

在 MySQL 数据库中 的验证 SQL 语句:

[root@localhost][testdb]> CREATE TABLE tb_test (->     id INT-> );
Query OK, 0 rows affected (0.01 sec)[root@localhost][testdb]> begin;
Query OK, 0 rows affected (0.00 sec)[root@localhost][testdb]> insert into tb_test(id) values(1001);
Query OK, 1 row affected (0.00 sec)[root@localhost][testdb]> select * from tb_test;
+------+
| id   |
+------+
| 1001 |
+------+
1 row in set (0.00 sec)[root@localhost][testdb]> SELECT non_existent_function(); 
ERROR 1305 (42000): FUNCTION testdb.non_existent_function does not exist
[root@localhost][testdb]> 
[root@localhost][testdb]> select * from tb_test;
+------+
| id   |
+------+
| 1001 |
+------+
1 row in set (0.00 sec)[root@localhost][testdb]> commit;
Query OK, 0 rows affected (0.00 sec)[root@localhost][testdb]> 
[root@localhost][testdb]> select * from tb_test;
+------+
| id   |
+------+
| 1001 |
+------+
1 row in set (0.00 sec)[root@localhost][testdb]> 

从上述的验证结果中,可知:
与 MySQL 不同,PostgreSQL 数据库在出现错误后,即使后续语句在语法和语义上完全正确,也不会再接受任何语句。即便此时发出 COMMIT 语句,PostgreSQL 也会回滚整个事务。

事务保存点

在 PostgreSQL 数据库中,保存点使用 savepoint 子句,语法如下:

postgres=# \h savepoint;
Command:     SAVEPOINT
Description: define a new savepoint within the current transaction
Syntax:
SAVEPOINT savepoint_namepostgres=# 

演示- 示例(01)
如下示例中,即使有保存点,当遇到报错时,进行提交。
此时也不会从保存点保存数据,因为:在 PostgreSQL 中,只有 没有发生错误的事务 才能被提交

postgres=# select * from tb_test;id 
----
(0 rows)postgres=# begin;
BEGIN
postgres=# insert into tb_test values(1001);
INSERT 0 1
postgres=# 
postgres=# select * from tb_test;id  
------1001
(1 row)postgres=# savepoint step01;
SAVEPOINT
postgres=# 
postgres=# select 1/0;
ERROR:  division by zero
postgres=# 
postgres=# select * from tb_test;
ERROR:  current transaction is aborted, commands ignored until end of transaction block
postgres=# 
postgres=# commit;
ROLLBACK
postgres=# 
postgres=# select * from tb_test;id 
----
(0 rows)postgres=# 

演示- 示例(02)
如下示例中,有保存点,当遇到报错时,回退到保存点 进行提交。
这种情况下,事务可以提交成功。

postgres=# select * from tb_test;id 
----
(0 rows)postgres=# begin;
BEGIN
postgres=# insert into tb_test values(1001);
INSERT 0 1
postgres=# savepoint step01;
SAVEPOINT
postgres=# select * from tb_test;id  
------1001
(1 row)postgres=# select 1/0;
ERROR:  division by zero
postgres=# 
postgres=# select * from tb_test;
ERROR:  current transaction is aborted, commands ignored until end of transaction block
postgres=# 
postgres=# rollback to savepoint step01;
ROLLBACK
postgres=# 
postgres=# select * from tb_test;id  
------1001
(1 row)postgres=# commit;
COMMIT
postgres=# 
postgres=# select * from tb_test;id  
------1001
(1 row)postgres=# 

演示- 示例(03)
如下示例中,事务提交后,再尝试**回退到保存点** 。

postgres=# select * from tb_test;id  
------1001
(1 row)postgres=# 
postgres=# begin;
BEGIN
postgres=# insert into tb_test values(1002);
INSERT 0 1
postgres=# savepoint step01;
SAVEPOINT
postgres=# select * from tb_test;id  
------10011002
(2 rows)postgres=# commit;
COMMIT
postgres=# rollback to savepoint step01;
ERROR:  ROLLBACK TO SAVEPOINT can only be used in transaction blocks
postgres=# 

在事务已经被结束之后,将无法再次返回到一个之前的保存点。

DDL 事务

在 PostgreSQL 数据库中,除了少量(drop database | create tablespace/drop tablespace 等),PostgreSQL中所有的 DDL 都是事务性的。

例如
在一个事务块中运行 DDL(改变数据结构命令),在MySQL中,当前事务中的 DDL 将会被隐式提交。但在 PostgreSQL 数据库中,可回滚。

MySQL 数据库,示例验证:

[root@localhost][testdb]> desc tb_test;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)[root@localhost][testdb]> 
[root@localhost][testdb]> begin;
Query OK, 0 rows affected (0.00 sec)[root@localhost][testdb]> ALTER TABLE tb_test -> MODIFY COLUMN id CHAR(10);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0[root@localhost][testdb]> rollback;
Query OK, 0 rows affected (0.00 sec)[root@localhost][testdb]> 
[root@localhost][testdb]> desc tb_test;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id    | char(10) | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
1 row in set (0.00 sec)[root@localhost][testdb]> 

PostgreSQL 数据库,示例验证:

postgres=# \d tb_test;Table "public.tb_test"Column |  Type   | Modifiers 
--------+---------+-----------id     | integer | postgres=# 
postgres=# begin;
BEGIN
postgres=# 
postgres=# ALTER TABLE tb_test 
postgres-# ALTER COLUMN id TYPE CHAR(10);
ALTER TABLE
postgres=# 
postgres=# \d tb_test;Table "public.tb_test"Column |     Type      | Modifiers 
--------+---------------+-----------id     | character(10) | postgres=# 
postgres=# rollback;
ROLLBACK
postgres=# 
postgres=# \d tb_test;Table "public.tb_test"Column |  Type   | Modifiers 
--------+---------+-----------id     | integer | postgres=# 

若有转载,请标明出处:
https://blog.csdn.net/CharlesYuangc/article/details/149165365

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

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

相关文章

Linux:多线程---深入互斥浅谈同步

文章目录1. 互斥1.1 为什么需要互斥1.2 互斥锁1.3 初谈互斥与同步1.4 锁的原理1.5 可重入VS线程安全1.6 死锁1.7 避免死锁的算法(扩展)序:在上一章中我们知道了线程控制的三个角度:线程创建、线程等待和线程终止,分别从…

适用于 vue2、vue3 的自定义指定:v-int(正整数)

在项目中,我们经常会遇到输入框只允许输入数字的情况,下面是一段自定义指定 代码,复制到项目中,注册指定即可使用用法如下: 创建一个IntInput.js 文件,将下面代码复制到文件中保存在项目中的 main.js 文件中…

学习基于springboot秒杀系统-环境配置(接口封装,mybatis,mysql,redis(Linux))

文章目录前言创建springboot项目封装controller层输入输出rest api 的json输出返回页面集成mybatis集成redis下载虚拟机和centos下载redis.tar.gz上传redis.tar.gz 到虚拟机前言 今天开始记录学习秒杀系统-课程是基于慕课上的搜索秒杀系统的课程,老师讲解非常好。这…

stm32达到什么程度叫精通?

STM32达到什么程度叫精通?一个十年老兵的深度反思 前言:精通二字,重如泰山 每次有人问我"STM32达到什么程度叫精通"这个问题,我都会沉默很久。 不是因为这个问题难回答,而是因为"精通"这两个字太重…

微软上线Deep Research:OpenAI同款智能体,o3+必应双王炸

今天凌晨,微软在官网宣布,Azure AI Foundry中上线Deep Research公开预览版。这是支持API和SDK的OpenAI 高级智能体研究能力产品,并且Azure 的企业级智能体平台完全集成。Deep Research是OpenAI在今年4月25日发布的最新产品,能够像…

Spring Batch终极指南:原理、实战与性能优化

🌟 Spring Batch终极指南:原理、实战与性能优化单机日处理10亿数据?揭秘企业级批处理架构的核心引擎!一、Spring Batch 究竟是什么?Spring batch是用于创建批处理应用程序(执行一系列作业)的开源…

【Part 3 Unity VR眼镜端播放器开发与优化】第四节|高分辨率VR全景视频播放性能优化

文章目录《VR 360全景视频开发》专栏Part 3|Unity VR眼镜端播放器开发与优化第一节|基于Unity的360全景视频播放实现方案第二节|VR眼镜端的开发适配与交互设计第三节|Unity VR手势交互开发与深度优化第四节|高分辨率V…

TCP/IP协议基础

TCPIP协议基础 网络模型 -OSI参考模型 -OSI参考模型各层功能 -TCP/IP网络模型 -TCP/IP协议栈OSI参考模型 – 为了解决网络设备之间的兼容性问题,国际标准化组织ISO于1984年提出了OSI RM(开放系统互连参考模型)。 OSI参考模型一共有七层&#…

【Nginx】Nginx代理WebSocket

1.websocketWebSocket 是一种网络通信协议,它提供了在单个 TCP 连接上进行全双工(双向)通信的能力假设需求:把 ws://192.168.0.1:8088/ws-api/websocket/pushData代理到ws://192.168.0.156:8888/websocket/pushData;同…

Spring AI Alibaba Graph使用案例人类反馈

1、Spring AI Alibaba Graph 是社区核心实现之一,也是整个框架在设计理念上区别于 Spring AI 只做底层原子抽象的地方,Spring AI Alibaba 期望帮助开发者更容易的构建智能体应用。基于 Graph 开发者可以构建工作流、多智能体应用。Spring AI Alibaba Gra…

本地部署jenkins持续集成

一、准备环境(jdk版本跟Tomcat版本要匹配) java jdk 环境(版本是11.0.21) jenkins war包(版本是2.440.3) Tomcat (版本是 9.0.84) 二、安装步骤 1、安装jdk环境 1)先安装java环境,安装完成后配置环境变量,参考上…

基于Java+Maven+Testng+Selenium+Log4j+Allure+Jenkins搭建一个WebUI自动化框架(1)搭建框架基本雏形

本次框架使用Maven作为代码构建管理&#xff0c;引用了PO模式&#xff0c;将整体的代码分成了页面层、用例层、业务逻辑层。框架搭建流程&#xff1a;1、在pom.xml中引入依赖&#xff1a;<!-- https://mvnrepository.com/artifact/io.appium/java-client --> <depende…

从零构建MCP服务器:FastMCP实战指南

引言&#xff1a;MCP协议与FastMCP框架 Model Context Protocol&#xff08;MCP&#xff09;是连接AI模型与外部服务的标准化协议&#xff0c;允许LLM&#xff08;如Claude、Gemini&#xff09;调用工具、访问数据。然而&#xff0c;直接实现MCP协议需要处理JSON-RPC、会话管理…

基于FPGA的智能小车设计(包含代码)/ 全栈FPGA智能小车:Verilog实现蓝牙/语音/多传感器融合的移动平台

首先先声明一下&#xff0c;本项目已经历多轮测试&#xff0c;可以放心根据我的设计进行二次开发和直接套用&#xff01;&#xff01;&#xff01; 代码有详细的注释&#xff0c;方便同学进行学习&#xff01;&#xff01; 制作不易&#xff0c;记得三连哦&#xff0c;给我动…

Object.defineProperties 详解

Object.defineProperties 详解 Object.defineProperties 是 JavaScript 中用于在一个对象上定义或修改多个属性的方法。它是 Object.defineProperty 的复数版本&#xff0c;允许你一次性定义多个属性。 基本语法 Object.defineProperties(obj, props)obj&#xff1a;要在其上定…

MyBatis-Plus:深入探索与最佳实践

MyBatis-Plus作为MyBatis的增强版&#xff0c;已经在Java开发中得到了广泛应用。它不仅继承了MyBatis的所有功能&#xff0c;还提供了许多强大的扩展功能&#xff0c;帮助开发者提升开发效率和代码质量。本文将深入探讨MyBatis-Plus的高级特性及其在实际项目中的最佳实践。一、…

劳斯莱斯数字孪生技术:重构航空发动机运维的绿色革命

在航空工业迈向智能化的浪潮中&#xff0c;劳斯莱斯以数字孪生技术为核心&#xff0c;构建了发动机全生命周期管理的创新范式。这项技术不仅重新定义了航空发动机的维护策略&#xff0c;更通过数据驱动的决策体系&#xff0c;实现了运营效率与生态效益的双重突破。本文将从技术…

NPM组件 querypilot 等窃取主机敏感信息

【高危】NPM组件 querypilot 等窃取主机敏感信息 漏洞描述 当用户安装受影响版本的 querypilot 等NPM组件包时会窃取用户的主机名、用户名、工作目录、IP地址等信息并发送到攻击者可控的服务器地址。 MPS编号MPS-2kgq-v17b处置建议强烈建议修复发现时间2025-07-05投毒仓库np…

创业商业融资计划书PPT模版

创业商业融资计划书PPT模版&#xff1a;https://pan.quark.cn/s/25a043e4339e