| PostgreSQL 7.4 文檔 | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 3. 高級特性 | Fast Forward | Next |
事務是所有數據庫系統的一個基本概念。 一次事務的要點就是它把多個步驟捆綁成了一個單一的,不成功則成仁的操作。 其它並發的事務是看不到在這些步驟之間的中間狀態的,並且如果發生了一些問題, 導致該事務無法完成,那麼所有這些步驟都完全不會影響數據庫。
比如,假設一個銀行的數據庫包含各種客戶帳戶的餘額,以及每個分行的總餘額。 假設我們要記錄一次從 Alice 的帳戶到 Bob 的帳戶的金額為 $100.00 的支付動作。那麼,完成這個任務的簡單到極點的 SQL 命令象下面這樣
UPDATE accounts SET balance = balance - 100.00
WHERE name = 'Alice';
UPDATE branches SET balance = balance - 100.00
WHERE name = (SELECT branch_name FROM accounts WHERE name = 'Alice');
UPDATE accounts SET balance = balance + 100.00
WHERE name = 'Bob';
UPDATE branches SET balance = balance + 100.00
WHERE name = (SELECT branch_name FROM accounts WHERE name = 'Bob');
這些命令的細節在這兒並不重要;重要的是這裡牽涉到了好幾個獨立的更新來完成這個相當簡單的操作。 我們的銀行官員會希望要麼所有這些更新都生效,要麼全部不起作用。 我們當然不希望一次系統崩潰就導致 Bob 收到 100 塊不是 Alice 支付的錢, 也不希望 Alice 老是不花錢從 Bob 那裡拿到物品。我們需要保證:如果在操作的過程中出了差錯, 那麼所有這些步驟都不會發生效果。把這些更新組合成一個事務就給予我們這樣的保證。 事務被認為是原子的:從其它事務的角度來看, 它要麼是全部發生,要麼完全不發生。
我們還需要保證:一旦一個事務完成並且得到數據庫系統的認可, 那麼它必須被真正永久地存儲,並且不會在隨後的崩潰中消失。 比如,如果我們記錄到了一個 Bob 撤單的動作, 那麼我們不希望僅僅在他走出銀行大門之後的一次崩潰就會導致對他的帳戶的扣減動作消失。 一個事務型數據庫保證一個事務所做的所有更新在事務發出完成響應之前都記錄到永久的存儲中(也就是磁盤)。
事務型數據庫的另外一個重要的性質和原子更新的概念關系密切: 當多個事務並發地運行的時候,那麼每個事務都不應看到其它事務所做的未完成的變化。 比如,如果一個事務正忙著計算所有分行的餘額總和, 那麼它不應該包括來自 Alice 的分行的扣帳和來自 Bob 分行的入帳,反之亦然。 所以事務必須是黑白分明的,不僅僅體現在它們在數據庫上產生的永久影響出發,而且體現在它們運轉時的自身的可視性上。 一個打開的事務做的更新在它完成之前是其它事務無法看到的,而到提交的時候所有更新同時可見。
在 PostgreSQL 裡,一個事務是通過把 SQL 命令用 BEGIN 和 COMMIT 命令包圍實現的。 因此我們的銀行事務實際上看起來象下面這樣
BEGIN;
UPDATE accounts SET balance = balance - 100.00
WHERE name = 'Alice';
-- 等等
COMMIT;
如果在該事務的過程中,我們決定不做提交(可能是我們剛發現 Alice 的餘額是負數), 那麼我們可以發出 ROLLBACK 命令而不是 COMMIT 命令,那麼到目前為止我們的所有更新都會被取消。
PostgreSQL 實際上把每個 SQL 語句當做在一個事務中執行的來看待。 如果你沒有發出 BEGIN 命令,那麼每個獨立的語句都有一個隱含的 BEGIN 和(如果成功的話) COMMIT 語句包圍在週圍。 一組包圍在 BEGIN 和 COMMIT 語句中間的語句有時候被稱做事務塊。
注意: 一些客戶庫自動發出 BEGIN 和 COMMIT, 因此你可能不需要特意請求就可以獲取事務塊的效果。查看你使用的接口的文檔。