在 PostgreSQL 的 Transaction 中即時讀取剛剛 INSERT 的資料:設計與實務經驗分享
Copyright Notice: This article is an original work licensed under the CC 4.0 BY-NC-ND license.
If you wish to repost this article, please include the original source link and this copyright notice.
Source link: https://v2know.com/article/1130
在日常開發中,我們經常會遇到這樣的需求流程:
-
新增一筆資料(
INSERT
)到資料表。 -
緊接著查詢剛剛新增的這筆資料的欄位(
SELECT
)。 -
根據這筆查詢結果,執行後續的資料更新(
UPDATE
)。
那麼問題來了:在同一個交易(Transaction)中,我們真的能馬上 SELECT 到剛剛 INSERT 的資料嗎?
答案是——當然可以!
以下是我們在實務專案中遇到的實際情境與 PostgreSQL 的設計解釋。
一個實際範例
我們在一個 foreach (groups)
迴圈中執行以下流程:
-- Step 1: 新增資料
INSERT INTO link_tbl (link_cd, kobetu_cd, matome_cd_uke, ...)
VALUES (...);
-- Step 2: 查詢剛剛那筆的 matome_cd_uke
SELECT matome_cd_uke
FROM link_tbl
WHERE kobetu_cd = :kc
ORDER BY link_cd DESC
LIMIT 1;
這兩段 SQL 都是在 同一個 NpgsqlConnection、同一個 NpgsqlTransaction tran 中執行的。
結果就是:我們的 SELECT 查詢可以即時讀到剛剛 INSERT 的資料,毫無問題。
PostgreSQL 的保證:Read Committed 隔離層級
PostgreSQL(以及大多數主流的 RDBMS,例如 SQL Server、MySQL)預設使用的交易隔離層級是 Read Committed。
這代表:
-
在同一個交易(Transaction)中,你自己所做的 INSERT、UPDATE,立刻就能被後續的 SELECT 查到。
-
只有其他連線(Connection)上的查詢,必須等到你 COMMIT 之後,才會看到這筆資料。
所以,只要你確保以下兩點:
-
SELECT、INSERT、UPDATE 都使用 同一條 Connection;
-
並且共用 同一個 Transaction tran;
那麼就可以放心地在程式執行順序上,先 INSERT → 後 SELECT,完全查得到。
實務上的保險作法
雖然我們知道 SELECT 查得到剛剛 INSERT 的資料,但我們也會這麼寫:
SELECT matome_cd_uke
FROM link_tbl
WHERE kobetu_cd = :kc
ORDER BY link_cd DESC
LIMIT 1;
這裡的 ORDER BY link_cd DESC LIMIT 1
是保險機制:
假設歷史上有多筆同一個 kobetu_cd
的資料,我們一定要拿「最新那筆」,這通常由自增欄位 link_cd
控制。
Bonus:減少資料庫查詢次數的技巧(版本 B)
如果你希望減少資料庫的查詢次數(尤其在大量迴圈中),還可以考慮這個優化:
-
第一次 INSERT 完之後,直接將
(kobetu_cd, matome_cd_uke)
存入一個 Dictionary -
後續要用時,直接從 Dictionary 取用,而不是再次 hit 資料庫
兩種做法都正確,看你是否偏向資料庫即時查詢,還是 prefer 將中間結果緩存起來、減少 DB 負擔。
結語
這篇文章的重點總結如下:
✅ PostgreSQL 在同一個交易中能馬上 SELECT 到自己剛剛 INSERT 的資料
✅ Read Committed 是 PostgreSQL 預設的隔離層級,提供這項保證
✅ ORDER BY DESC LIMIT 1
是實務中常用的查詢技巧,確保抓到最新一筆
✅ 如需效能最佳化,可將結果暫存在 Dictionary,避免重複查詢
透過掌握這些交易與隔離層級的概念,你就能更靈活且高效地設計資料處理流程。
This article was last edited at