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

#64 資料庫引擎交易 (Transaction) 進行中的讀寫異常

前面的文章曾談到交易 (Transaction) 需要具有 ACID 的特性.在一個繁忙的資料庫系統中一定會有許多的交易同時執行,這篇文章便來談論許多交易同時執行時會遇到那些挑戰.

許多交易在進行時,非常有可能會遇到對相同的資料進行讀或寫的動作.如果所有的交易對相同的資料進行讀的動作,則這情況並沒有什麼好擔心的,因為所有的交易對這份資料都是讀的動作,早讀和晚讀都是同一個答案,所以不會造成任何的資料異常現象.但如果情況變成其中有一個交易或多個交易對同一份資料進行寫的動作時,那麼早寫和晚寫就會有很大的影響了.因此,我們在乎的情況便是當有交易在進行寫的動作.以下假設某個資料庫系統中有兩個交易,這兩個交易會對同一份資料進行讀和寫的動作:



如上圖所示,T1 做的動作是 A=A-100 和 B=B+100,T2 做的動作是 A=A*1.5 和 B=B*1.5.如果交易執行的情況如上圖的話,假設 A 和 B 的初始值都是 300,你認為當這兩個交易完成後,A 和 B 的值會多少呢 ? 沒算錯的話,A 應是 300,B 應是 550.如果 T1 和 T2 執行的情況不是像上圖一樣,而是 T1 先執行,完成後再執行 T2,此時答案是多少呢? 沒算錯的話,A 還是 300,但 B 是 600.這時你就會發現怪怪的,執行的順序果然會影響答案,這可是不得了的大事呀.如果你把 A 和 B 想像成是銀行中的戶頭,而 T1 就像在執行匯款的動作,T2 就像是在執行加值的動作.這兩組不同目的動作是可以同時被觸發的,但很顯然地你一定發現 T1 在執行動作時,T2 不應該執行,因為他們會對相同的資料進行寫的動作.如果你允許他們可以同時對相同資料進行寫的動作,則就會發生資料異常的現象.所謂資料異常就是指不應該發生的情況.正常的情況是 T1 先執行再執行 T2,或是 T2 先執行再執行 T1.我們再來看另一種例子:



這一個例子是 T1 的讀寫動作完成後 T2 才開始進行讀寫,但最大的差別是 T2 在進行讀寫時,T1 還沒有 commit.等到 T2 commit 完成之後,最後 T1 才決定 abort.這種情況也是我們不希望看到的,因為這也是一種資料異常的現象,因為 T2 在對 A資料進行讀寫時,它的基礎是建立在 T1 對 A 完成的結果上,結果 T1 對其結果是否定的 (abort),所以 T2 的結果就便成是一個大笑話了.

看到這裡時,你就可以知道當某一個交易對某一個資料進行 "寫" 的動作時,在這交易尚未完成前 (Commit or Abort),我們不希望其他交易能對相同資料進行 "讀" 和 "寫" 的動作.相同地,當某一個交易對某一個資料進行 "讀" 的動作時,在這交易尚未完成前 (Commit or Abort),我們也不希望其他交易能對相同資料進行 "寫" 的動作.如下圖所示:



為了防止以上資料異常的現象發生,資料庫引擎裡需要某些特別的設計來防止這類的事情發生,這個特別的設計稱為 Locking.也就是當某交易在對某份資料進行動作時,便把該份資料鎖住讓其他交易無法使用該資料.下一篇文章將會來談談這個鎖資料的內容.

Share:

Related Posts:

0 意見:

張貼留言