The two most important days in your life are the day you were born and the day you find out why. -Mark Twain

#58 資料庫引擎對交易 (Transaction) 的執行情況

在上次文章裡介紹了基礎的交易 (Transaction) 性質與特點,讓你可以了解為何關聯式資料庫引擎需要它.在一般的情況下,一個資料庫引擎在同一個時間內服務的應用程式非常可能不只一個,而且同一個應用程式也可能在同一個時間發出兩個不同的交易來要求資料庫引擎執行.因此,我們都知道一個資料庫引擎在同一時間執行多個來自用戶端的交易是相當平常的事情.同時可以服務多個用戶端等於是增加了整個系統的處理效能,也因為要同時服務多個用戶端,資料庫引擎的效能對於磁碟存取就會變得相當敏感.因為磁碟存取速度快,整體效能才夠快.但只有磁碟效率快就夠了嗎? 在上次文章裡介紹了交易的特點之後,你就能明白光是快還不夠,還需要在多個交易執行讀取之間不造成衝突才行.因此,資料庫引擎的設計就會面臨兩個挑戰:

1. 如何執行多個交易時還能保持資料的正確性?
2. 如果硬體出錯或是用戶端取消交易執行時,資料庫引擎該如何處理以保持資料的正確性.

為了面對這兩個挑戰,資料庫引擎得引進一個排程 (Schedule) 的想法.所謂 Schedule 是指一連串的動作 (讀或寫),而這一連串的動作可以是由不同的交易而來的,更重要的是不論這份 Schedule 裡那一個交易先執行,其結果都該和 Schedule 的結果一致.這樣講可能有點抽象,直接看下圖:

資料來源: 我以前在學校的筆記

上圖是一個 Schedule,裡面有兩個交易,分別是 T1 和 T2,其中 T1 有 4 個動作,而 T2 有兩個.時間軸是由上而下,所以 R(A) 是整個 Schedule 裡第一個動作,它代表到 A 做讀取動作,而 W(C) 是最後一個,它代表到 C 做寫入動作.這份 Schedule 安排的很好,因為 T1 讀寫的對象和 T2 完全不同,所以這兩個交易之間不會產生衝突的情況.而每一個交易最後都會有一個 commit 的動作,用來告訴資料庫引擎可以把放在暫存區的結果寫回到磁碟上.如果資料庫引擎可以安排出好的 Schedule,似乎就能克服先前說的兩個挑戰.接下來看一個簡單的例子.

假設銀行要執行兩個交易,一個交易是做轉帳,從 A 帳戶轉 100 元到 B 帳戶,另一個交易是做分派利息,兩個帳戶同時增加 50% 的利息.以動作來看,第一個交易有兩個動作,A=A-100 以及 B=B+100,第二個交易也有兩個動作,A=A*1.5 和 B=B*1.5.假設,不同的用戶端分別同時發出這兩個交易,那麼資料庫引擎該怎麼設計 Schedule? (無法保證 T1 , T2 那一個會開始執行)

如果 Schedule 被安排的如下:

資料來源: 我以前在學校的筆記

這份 Schedule 是可行的,因為它的結果跟單獨先執行 T1 再執行 T2 是一樣的.如果 A , B 都有 100,先執行 T1 再執行 T2,這樣 A=0, B=300 符合這份 Schedule 的預期,所以它是可行的.

如果 Schedule 被安排成另一種:

資料來源: 我以前在學校的筆記

這份 Schedule 似乎就不行了,因為順序影響結果.假設 A, B 一開始有 100,先執行 T1 再執行 T2,變成 A=0, B=300,但是這份 Schedule 完成之後是 A=0, B=250,顯然這份 Schedule 裡動作的順序安排的不適合了.

設計出適合的 Schedule 讓資料庫引擎可以一起執行多個交易也算是增加效能的方法之一.下一篇文章會再繼續談到為何需要好的 Schedule 以及動作衝突時如何解決.

Share:

0 意見:

張貼留言