文章

PostgreSQL - 第 14 天 - 交易管理 (TRANSACTION)

課程簡介

交易是一組 SQL 操作的集合,這些操作要么全部成功,要么全部失敗,以確保數據庫的一致性。交易特別重要,因為它可以避免數據在操作過程中的不完整或不一致狀況。


什麼是交易?

在數據庫中,交易(Transaction)是一組邏輯操作單位。交易可以將多個 SQL 語句組合在一起,這些語句作為一個整體來執行。這意味著交易中的所有操作要么全部執行成功,要么全部回滾失敗。

交易具有以下四個特性,稱為 ACID 特性:

  • 原子性(Atomicity):交易中的所有操作要么全部成功,要么全部失敗。
  • 一致性(Consistency):交易開始和結束時,數據庫必須處於一致的狀態。
  • 隔離性(Isolation):交易之間互不影響,即使多個交易同時執行,它們的效果應該和串行執行一樣。
  • 持久性(Durability):一旦交易提交,對數據的更改將永久保存在數據庫中。

交易管理語句

PostgreSQL 提供以下語句來管理交易:

  • BEGIN:開始一個新交易。
  • COMMIT:提交交易,保存所有更改。
  • ROLLBACK:回滾交易,撤銷所有更改。
  • SAVEPOINT:在交易中建立保存點,以便部分回滾。

基本交易操作

在開始和結束交易時,可以使用以下流程:

1
2
3
BEGIN; -- 開始交易
-- 執行一些 SQL 操作
COMMIT; -- 提交交易,保存更改

如果在交易過程中出現錯誤,可以使用 ROLLBACK 來撤銷所有更改:

1
2
3
BEGIN;
-- 執行一些 SQL 操作
ROLLBACK; -- 出錯時回滾交易

範例:交易的使用

假設我們有兩個帳戶,帳戶 A 和帳戶 B,我們需要從帳戶 A 向帳戶 B 轉賬。這個操作需要兩步:

  1. 從帳戶 A 扣款。
  2. 向帳戶 B 存款。

這兩步需要作為一個交易執行,如果其中任何一個操作失敗,我們希望所有更改都回滾。

範例 SQL:

1
2
3
4
5
6
BEGIN; -- 開始交易

UPDATE 帳戶 SET 餘額 = 餘額 - 1000 WHERE 帳戶名 = 'A'; -- 從帳戶 A 扣款
UPDATE 帳戶 SET 餘額 = 餘額 + 1000 WHERE 帳戶名 = 'B'; -- 向帳戶 B 存款

COMMIT; -- 提交交易

如果在其中一條更新語句中出現錯誤,可以使用 ROLLBACK 來撤銷整個交易:

1
2
3
4
5
6
7
BEGIN;

UPDATE 帳戶 SET 餘額 = 餘額 - 1000 WHERE 帳戶名 = 'A';
UPDATE 帳戶 SET 餘額 = 餘額 + 1000 WHERE 帳戶名 = 'B';

-- 出錯時回滾
ROLLBACK;

使用 SAVEPOINT 部分回滾

SAVEPOINT 允許在交易過程中建立「保存點」,從而在出錯時回滾到特定保存點,而不必撤銷整個交易。這在較長的交易過程中尤其有用。

SAVEPOINT 語法

1
2
3
4
5
6
BEGIN;
-- 執行一些操作
SAVEPOINT 保存點名; -- 創建保存點
-- 執行更多操作
ROLLBACK TO 保存點名; -- 回滾到保存點
COMMIT;

範例

假設我們有以下步驟,並且希望如果在第二步出錯,只回滾第二步的操作,而保持第一步的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
BEGIN;

-- 步驟 1
UPDATE 帳戶 SET 餘額 = 餘額 - 500 WHERE 帳戶名 = 'A';

SAVEPOINT 步驟1; -- 保存點在步驟1後

-- 步驟 2
UPDATE 帳戶 SET 餘額 = 餘額 - 500 WHERE 帳戶名 = 'B';

-- 如果步驟2出錯
ROLLBACK TO 步驟1; -- 回滾到步驟1

COMMIT;

這樣,只會回滾步驟 2 的更改,而步驟 1 的更改會被保留。


隔離級別

在 PostgreSQL 中,交易的隔離級別影響交易之間的相互影響。常見的隔離級別包括:

  • READ UNCOMMITTED:允許讀取未提交的更改,容易產生髒讀(Dirty Read)。
  • READ COMMITTED:只能讀取已提交的更改,避免髒讀。
  • REPEATABLE READ:交易開始後,其他交易的更改不會影響該交易的結果。
  • SERIALIZABLE:最高級別,確保交易之間完全隔離,但可能導致性能降低。

可以使用以下語句來設置隔離級別:

1
SET TRANSACTION ISOLATION LEVEL 隔離級別;

本日總結

今天我們學習了 PostgreSQL 中的交易管理,了解了如何使用 BEGINCOMMITROLLBACKSAVEPOINT 來控制交易,以確保數據的一致性和可靠性。掌握交易管理的技巧可以幫助我們在數據庫操作中確保數據安全,避免不一致或不完整的數據問題。明天我們將深入學習數據完整性約束。

本文章以 CC BY 4.0 授權