在真實的網路行為上,一個只是點擊的動作常常會牽動對於多個數據的動作,這樣一系列動作的組成被稱為Transaction,中文有人說事務,也有人稱呼他為交易。
而ACID則是確保Transaction能正確可靠的四個特性。
後面會來稍微了解這個部分~
剛剛前提已經提到了關於Transaction的定義。
原則上,我們會希望當Transaction進行的時候,資料庫要像是時間停止一樣,直到commit之前所有的資料都保持不動;
而其他的事務的操作若有取得與前面事務相關的資料時,應該以前面事務的最終結果為結果。
ANSI/ISO standard SQL 92舉出一些並非如此的錯誤:
有兩個Transaction分別為A及B,若A的操作將包含更改一個欄位的資料,B這時候在A尚未commit(註1)的時候去讀取,並取得了更新後的結果,這就稱為Dirty Reads
為什麼這樣是一種錯誤呢?原因在於A並未確定已經成功了,若他失敗,將會把資料從已更新的資料退回,這時候B使用到的值就是錯誤的。
註1: 一個Transaction的commit代表在這個Transaction的所有操作都被確定完成了。
一個Transaction裡面,讀取兩次相同欄位,卻得到不同結果,稱為Non-Repeatable Reads
一個Transaction裡面,進行兩次查詢,得到不同數量的結果,就稱為Phantom Reads
看起來跟Non-Repeatable Reads有點相像,差異應該是讀取的層級不太一樣,以SQL的講法,Phantom Reads是發生在table內的等級,而Non-Repeatable Reads則是row內的等級,所以意思是,Non-Repeatable Reads跟Phantom Reads確實是可能在同一次搜尋裡面發生的。
為了避免上述的錯誤,大部分的關聯式資料庫都遵循這個原則,包括
全有全無,Transaction的操作要就全部發生,要就全部沒有,視為一個整體。
有一個說法是我覺得很清楚的
一般來說,原子性 意為某樣東西不可在被切割的更小塊。但在計算機領域中,則是指在多執行緒底下,某個執行緒若執行一個原子操作 (atomic operation),另一個執行緒無法看到該操作中的半完成狀態,只有操作前跟操作後兩個狀態。
-- Transactions (1) - ACID
在事務開始之前和事務結束以後,資料庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設約束、觸發器、級聯回滾等
-- 維基百科
這邊在維基百科其實說的有點抽象,但我看到一些其他的說法,包括:
我覺得一致性這邊要提到的約束其實是泛指所有,上面的說法都可能是其中一個部分,比如schema可能會限制unique index、另外不在schema中的約束可能是FK constraint等等的。
不過這裡的一致性也部分受到原子性保護著,比如說錯誤的操作因為原子性的全有全無機制,不會因此出現例外,而是會回到原本的狀態,這樣也就確保錯誤時的一致性不會被破壞了。
這裡指的是當多個Transaction併發(concurrent)時,不會互相造成影響。
最完美的作法當然後依序執行,也就是每次只完成一個Transaction,但這樣效能太差,這不就代表沒有併發嗎XD。
所以後面就會出現不同等級的隔離,都相對於依序執行隔離來的弱,有機率發生併發,但是在效能、情境上考量後可接受。
而開發者就需要了解不同層級的差異,以盡可能減少併發造成的bug,也就是前面提到的三種錯誤。
以下分為幾個層級,由低到高分別為:
保證A事務已更新但未commit的資料,B事務僅可讀取。
因為可以讀取其他Transaction尚未commit的結果,其實意思幾乎等同於沒隔離了XD
不過他的意義還是在的,想像一下若沒有這層隔離會發生的狀況:
原本預期嘗試更新為2就因此消失了,因此此層還是能至少避免更新的遺失。
此隔離性會發生的問題包括:
保證讀取到的資料都是經過確認(commit)的。
因此可以避免髒讀。
為什麼無法避免其餘錯誤呢?
有一個案例如下
這樣就發生不可重複讀了。
同上,如果這裡的更新變成插入資料一樣無法避免幻讀。
此隔離性會發生的問題包括:
保證同一次事務,取得的資料都相同。
此隔離性會發生的問題包括:
以效能換取隔離。
若Transaction完成,就算出現錯誤,已經完成操作的資料也應該保持原樣、永久的。
這次大致了解了Transaction,以及保持Transaction正確可靠的ACID。
不過其中在隔離性的部分雖然介紹了層級,但各資料庫實現這些層級隔離的方式完全是看他們自己XD
通常會應用到關於鎖Lock的觀念,不過這部分就只好留待以後了~~
明天會了解一下與DB效能有關的話題-N+1 problem。
此文章同步發表於部落格,歡迎來逛逛~
Transactions (1) - ACID
What is a database transaction?
簡介隔離層級
Transaction 併發錯誤與隔離層級 - (1)
資料庫交易的 Isolation