簡介隔離層級

有點晚了,但是還是想寫點東西,今天簡單談一下數據庫中的隔離性,隔離性是交易的保證之一,表示交易與交易之間不互相干擾,好像同時間就只有自己的交易存在一樣,隔離性保證的基本方式是在資料庫層面,對資料庫或相關欄位鎖定,在同一時間內只允許一個交易進行更新或讀取。

先來看看沒有對資料庫進行鎖定下,可能發生的問題:

更新遺失(lost update)
基本上就是指某個交易對欄位進行更新的資訊,因另一個交易的介入而遺失。

例如,兩個以上交易在進行同一欄位的更新時,若沒有對欄位進行鎖定,若交易A進行COMMIT,交易B因故ROLLBACK,則交易A所作的更新就會發生遺失的問題:

交易A更新欄位1
交易B更新欄位1
交易A COMMIT
交易B ROLLBACK
另一種可能的情況是,如果交易A在交易B前後進行更新與COMMIT,則交易B所作的更新將會遺失,又稱爲二次更新遺失(second lost update),例如:

交易A更新欄位1
交易B更新欄位1
交易B COMMIT
交易A COMMIT
在以上的情況,交易B所進行的更新將會遺失。

髒讀(dirty read)
兩個交易同時進行,其中一個交易更新資料,另一個交易讀取了尚未COMMIT的資料,就有可能發生髒讀問題。例如:

交易A更新欄位1
交易B讀取欄位1
交易A ROLLBACK
交易B COMMIT
在以上的情況下,交易B讀取的是不正確的資料。

無法重複的讀取(unrepeatable read)
某個交易兩次讀取同一欄位的資料並不一致,例如,如果交易A在交易B前後進行資料的讀取,則會得到不同的結果。

交易A讀取欄位1
交易B更新欄位1
交易B COMMIT
交易A讀取欄位1
在以上的情況,交易A讀取兩次欄位1,但卻得到不同的結果。

幻讀(phantom read)
如果交易A進行兩次查詢,在兩次查詢之中有個交易B插入一筆新資料或刪除一筆新資料,第二次查詢時得到的資料多了第一次查詢時所沒有的筆數,或者少了一筆。

交易A進行查詢得到五筆資料
交易B插入一筆資料
交易B COMMIT
交易A進行查詢得到六筆資料

隔離交易的基本方式是鎖定資料庫,但完全的鎖定資料庫實務上並不會這麼作,因爲完全的鎖定資料庫將導致嚴重的效能問題,因此實務上會根據資料讀寫更新的頻繁性,設定不同的交易隔離層級(transaction isolation level):

read uncommited
簡而言之,某個交易可以讀取另一個交易已更新但尚未commit的資料,所以允許dirty read,但不允許lost update,也就是允許交易B讀取交易A更新尚未COMMIT的資料,但在交易A進行COMMIT前,不允許其它交易再寫入(也就是寫入鎖定)。

這個隔離層級讀取錯誤資料的機率太高,一般不會採用這種隔離層級。

讀取的交易不會阻止其它的交易,一個未COMMIT的交易會阻止其它寫入的交易。
read commited
比read uncommited嚴格一些,簡而言之,某個交易僅可讀取另一個交易已commit的資料,所以允許unrepeatable read,但不允許dirty read,一筆交易正在讀取資料時,允許另一筆交易進行資料寫入,但不允許已經dirty的資料被讀取或寫入(shared read lock, exclusive write lock)。

讀取的交易不會阻止其它的交易,一個未COMMIT的交易會阻止其它所有的交易。
repeatable read
比read commited嚴格,在一個交易己讀取的資料,不允許其它交易進行資料寫入,不允許unrepeated read,但phantom read還是可能發生。

讀取的交易不會阻止其它讀取的交易,但會阻止其它寫入的交易,而寫入的交易會阻止所有其它的交易。

serializable
最嚴格的隔離層級,同一筆資料一次只能有一個交易,無法讓交易並行處理。

read uncommited出錯的機率太大,大部份的應用程式會選用read commited或repeatable read的隔離層級,而serializable執行完全的鎖定,嚴重傷害系統效能。

真正的鎖定系統是在資料庫系統上實作的,依各家廠商而有所不同,必須參考廠商的說明書,瞭解不同的隔離層級對應用程式的效能與擴展性有何影響。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章