【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
英文地址,請注明出處:http://en.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