# DB Transaction筆記 ###### tags: `Database` `Transaction` ## 目錄 [TOC] ## 認識Transaction Transaction(中文稱為交易,有些地方稱事務)是為了確保程式在處理的過程中只能全數成功才會正式寫到DB中,因此只會有兩種結果,要麼全部成功,要麼全部失敗。 這樣講好像有點模糊,舉個沒Transaction會GG的例子: - 使用網銀轉帳時,如果網銀沒有使用Transaction,轉錢的過程中突然被中斷了!那麼,當你的帳戶被扣款時,對方可能還沒有收到錢。這時你一定氣的跳腳🤬,你的錢可能已經被扣走了,但對方還沒有收到錢。 因此,資料庫系統可以在Transaction開始後,只要沒有確認成功`Commit`,就會回到交易開始前的狀態`Rollback`。 當程式中出現錯誤並需要全盤回覆原狀時,我們可以使用Transaction來保證資料正確性。 ## Transaction ACID特性 ### 原子性(Atomicity) 將整個交易啟動時到失敗或是成功時才會結束交易,因此這整段交易過程視為一個原子,是一個不可分割的邏輯單位。 ### 一致性(Consistency) 交易前後保持一致性,因此只要定義好Transaction過程重要做什麼,就要確保前後是要符合預期結果,來確保Transaction前後資料庫完整性沒有被破壞。 ### 隔離性(Isolation) Transaction過程中不能被任何別的Transaction影響。 當同一時間有兩筆資料同時進行交易,這兩筆交易的運作獨立,不會互相干擾防止不一致的結果。 ### 永久性(Durability) 一旦資料修改完成,變永久存在。 ## Transaction併發錯誤 就算前面說了這些Transaction的特性,但是在某些高併發狀況下,可能產生競爭危害(Race Condition),仍然會造成一些不可預期的錯誤 接下來都以兩次Transaction為例,T1為先開始的交易,T2為後開始的交易 ### 髒讀Dirty Read :::warning 交易(T1)讀到了交易(T2)尚未Commit的資料 ::: 可以從下圖中看到T2在更新產品數量時發生`Rollback`,因此導致T1先前讀到的數量是錯誤的  ### 不可重複讀Non-repeatable read :::warning 在交易(T1)過程中,因"另一個"交易(T2)提交了Commit,當次的交易(T1)前後查詢得到不同結果 ::: 也就是在兩次查詢之間,相同的資料可能會出現不同的結果,這個狀況會導致Transaction違反前面所說的一致性  ### 幻讀Phantom Read :::warning 一個交易(T1)過程中前後兩次查詢的資料總數不同,因為"另一個"交易(T2)使用INSERT或DELETE導致 :::  ## 資料庫隔離層級 隔離層級聽起來很複雜,可以把隔離層級當作水龍頭的開關,利用開關大小來控制水流的量,如果開的很大的話,水流得自然快(效能好),但就容易發生不可控制的狀況,反之亦然 在資料庫中就是利用隔離層級來做到解決一致性的難題,這些隔離機制是利用`鎖定`資源的概念實現的,另外實做上可能會搭配Queues的機制,不過在高併發的狀況下,Server能不能忍受這些流量也是需要考量的因素之一  ### Read Uncommitted 最寬鬆的隔離層級,如字面上說的,可以讀到其他Transaction尚未`Commit`的資料,可能造成前一節中所有錯誤「髒讀、不可重複讀、幻讀」 ### Read Committed 這個層級允許讀取已經`Commit`的資料,但是有可能發生「不可重複讀、幻讀」的狀況 ### Repeatable Read 在同一次Transaction的狀況下,資料庫只會讓讀取結果相同,這樣避免了不可重複讀的狀況,但仍能產生「幻讀」的結果 ### Serializable 最為嚴格的一個隔離層級,讓所有Transaction序列化執行,並且鎖定資源,確保相同時間只有一個Transaction在執行,用這個方法來避免所有發生的問題,效能最差,也最容易導致`Deadlock`問題 ### 補充: Deadlock 前面有提到這個詞就稍微說明一下,在併發狀況下Transaction互相鎖住對方的資源時就會造成Deadlock,這個時候程式就會進入死循環,直到被強制終止或是超時才會Rollback並且釋放資源  ## 結論 - Transaction在高併發狀況下會產生錯誤讀取的狀況 - 在高併發的狀況下,Transaction容易產生錯誤讀取的狀況。為了避免這種狀況,可以選擇使用高隔離層級,但這樣做會對效能產生影響,因此在實際應用時,需要根據當下的情境來做取捨。 ## 參考來源 [IT鐵人賽 前端工程師一起來種一棵後端技能樹吧! Day16~19](https://ithelp.ithome.com.tw/users/20113277/ironman/2937) - Database Transaction & ACID - Transaction 併發錯誤與隔離層級 [RDBMS - 錯誤讀取現象及交易隔離層級原理介紹與舉例](https://blog.kennycoder.io/2020/02/09/RDBMS-%E9%8C%AF%E8%AA%A4%E8%AE%80%E5%8F%96%E7%8F%BE%E8%B1%A1%E5%8F%8A%E4%BA%A4%E6%98%93%E9%9A%94%E9%9B%A2%E5%B1%A4%E7%B4%9A%E5%8E%9F%E7%90%86%E4%BB%8B%E7%B4%B9%E8%88%87%E8%88%89%E4%BE%8B/)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up