This article needs additional citations for verification . Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.(2009年1月) 看到wikipedia中文關于數據庫相關的幾個 經典 條
This article needs additional citations for verification. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.(2009年1月) |
看到wikipedia中文關于數據庫相關的幾個經典條目有點老舊,尤其和英文條目相比。確定開始翻譯其中幾篇,先從事務隔離等級開始。格式采用維基Sandbox發布后的格式。翻譯完后自己校對過幾遍,質量還可以。:-)
User:Pinuo
From Wikipedia, the free encyclopedia
Jump to: navigation, search
事務隔離(isolation)定義了數據庫系統中一個操作產生的影響什么時候以哪種方式可以對其他并發操作可見。隔離是事務ACID(原子性、一致性性、隔離性、持久性)四大屬性中的一個重要屬性。
Contents
1并發控制(Concurrency control)2隔離級別(Isolation levels)
2.1可序列化(Serializable)2.2可重復讀(Repeatable reads)2.3授權讀(Read committed)2.4未授權讀(Read uncommitted) 3默認隔離級別4讀現象(Read phenomena)
4.1臟讀(Dirty reads (Uncommitted Dependency))4.2不可重復讀(non-repeatable read)4.3幻影讀(phantom read) 5隔離級別、讀現象和鎖(Isolation Levels, Read Phenomena and Locks)
5.1隔離級別vs讀現象(Isolation Levels vs Read Phenomena)5.2隔離級別vs鎖持續時間(Isolation Levels vs Lock Duration) 6參照7相關條目8外部鏈接
并發控制(Concurrency control)
并發控制描述了數據庫處理隔離以保證數據正確性的機制。為了保證并行事務執行的準確執行數據庫和存儲引擎在設計的時候著重強調了這一點。典型的事務相關機制限制數據的訪問順序(執行調度)以滿足可序列化 和可恢復性。限制數據訪問意味著降低了執行的性能,并發控制機制就是要保證在滿足這些限制的前提下提供盡可能高的性能。經常在不損害正確性的情況下,為了達到更好的性能,可序列化的的要求會減低一些,但是為了避免數據一致性的破壞,可恢復性必須保證。
兩階段鎖是關系數據庫中最常見的提供了可序列化 和可恢復性的并發控制機制,為了訪問一個數據庫對象,事務首先要獲得這個對象的鎖。對于不同的訪問類型(如對對象的讀寫操作)和鎖的類型,如果另外一個事務正持有這個對象的鎖,獲得鎖的過程會被阻塞或者延遲。
隔離級別(Isolation levels)
在數據庫事務的ACID四個屬性中,隔離性是一個最常放松的一個。為了獲取更高的隔離等級,數據庫系統的鎖機制或者多版本并發控制機制都會影響并發。應用軟件也需要額外的邏輯來使其正常工作。
很多DBMS定 義了不同的“事務隔離等級”來控制鎖的程度。在很多數據庫系統中,多數的數據庫事務都避免高等級的隔離等級(如可序列化)從而減少對系統的鎖定開銷。程序 員需要小心的分析數據庫訪問部分的代碼來保證隔離級別的降低不會造成難以發現的代碼bug。相反的,更高的隔離級別會增加死鎖發生的幾率,同樣需要編程過程中去避免。
ANSI/ISOSQL定義的標準隔離級別如下。
可序列化(Serializable)
最高的隔離級別。
在基于鎖機制并發控制的DBMS實現可序列化要求在選定對象上的讀鎖和寫鎖保持直到事務結束后才能釋放。在SELECT 的查詢中使用一個“WHERE”子句來描述一個范圍時應該獲得一個“范圍鎖(range-locks)”。這種機制可以避免“幻影讀(phantom reads)”現象。
當采用不基于鎖的并發控制時不用獲取鎖。但當系統探測到幾個并發事務有“寫沖突”的時候,只有其中一個是允許提交的。這種機制的詳細描述見“'快照隔離”
可重復讀(Repeatable reads)
在可重復讀(REPEATABLE READS)隔離級別中,基于鎖機制并發控制的DBMS需要對選定對象的讀鎖(read locks)和寫鎖(write locks)一直保持到事務結束,但不要求“范圍鎖(range-locks)”,因此可能會發生“幻影讀(phantom reads)”
授權讀(Read committed)
在授權讀(READ COMMITTED)級別中,基于鎖機制并發控制的DBMS需要對選定對象的寫鎖(write locks)一直保持到事務結束,但是讀鎖(read locks)在SELECT操作完成后馬上釋放(因此“不可重復讀”現象可能會發生,見下面描述)。和前一種隔離級別一樣,也不要求“范圍鎖(range-locks)”。
簡而言之,授權讀這種隔離級別保證了讀到的任何數據都是提交的數據,避免讀到中間的未提交的數據,臟讀(dirtyreads)。但是不保證事務重新讀的時候能讀到相同的數據,因為在每次數據讀完之后其他事務可以修改剛才讀到的數據。
未授權讀(Read uncommitted)
未授權讀(READ UNCOMMITTED)是最低的隔離級別。允許臟讀(dirty reads),事務可以看到其他事務“尚未提交”的修改。
通過比低一級的隔離級別要求更多的限制,高一級的級別提供更強的隔離性。標準允許事務運行在更強的事務隔離級別上。(如在可重復讀(REPEATABLE READS)隔離級別上執行授權讀(READ COMMITTED)的事務是沒有問題的)
默認隔離級別
不同的DBMS默認隔離級別也不同。多少數據庫允許用戶設置隔離級別。有些DBMS在執行一個SELECT語句時使用額外的語法來獲取鎖(如SELECT ... FOR UPDATE來獲得在訪問的數據行上的排他鎖)
讀現象(Read phenomena)
ANSI/ISO 標準SQL 92涉及三種不同的一個事務讀取另外一個事務可能修改的數據的“讀現象”。
下面的例子中,兩個事務,事務1執行語句1。接著,事務2執行語句2并且提交,最后事務1再執行語句1. 查詢使用如下的數據表。
users |
||
id |
name |
age |
1 |
Joe |
20 |
2 |
Jill |
25 |
臟讀(Dirty reads (UncommittedDependency))
當一個事務允許讀取另外一個事務修改但未提交的數據時,就可能發生臟讀(dirty reads)。
臟讀(dirty reads)和不可重復讀(non-repeatablereads)類似。事務2沒有提交造成事務1的語句1兩次執行得到不同的結果集。在未授權讀(READ UNCOMMITTED)隔離級別唯一禁止的是更新混亂,即早期的更新可能出現在后來更新之前的結果集中。
在我們的例子中,事務2修改了一行,但是沒有提交,事務1讀了這個沒有提交的數據。現在如果事務2回滾了剛才的修改或者做了另外的修改的話,事務1中查到的數據就是不正確的了。
事務 1 |
事務 2 |
/* Query 1 */ SELECT age FROM users WHERE id = 1; /* will read 20 */ |
|
/* Query 2 */ UPDATE users SET age = 21 WHERE id = 1; /* No commit here */ |
|
/* Query 1 */ SELECT age FROM users WHERE id = 1; /* will read 21 */ |
|
ROLLBACK; /* lock-based DIRTY READ */ |
在這個例子中,事務2回滾后就沒有id是1,age是21的數據行了。
不可重復讀(non-repeatable read)
在一次事務中,當一行數據獲取兩遍得到不同的結果表示發生了“不可重復讀(non-repeatableread)”.
在基于鎖的并發控制中“不可重復讀(non-repeatable read)”現象發生在當執行SELECT 操作時沒有獲得讀鎖(read locks)或者SELECT操作執行完后馬上釋放了讀鎖;多版本并發控制中當沒有要求一個提交沖突的事務回滾也會發生“不可重復讀(non-repeatable read)”現象。
事務 1 |
事務 2 |
/* Query 1 */ SELECT * FROM users WHERE id = 1; |
|
/* Query 2 */ UPDATE users SET age = 21 WHERE id = 1; COMMIT; /* in multiversion concurrency control, or lock-based READ COMMITTED */ |
|
/* Query 1 */ SELECT * FROM users WHERE id = 1; COMMIT; /* lock-based REPEATABLE READ */ |
在這個例子中,事務2提交成功,因此他對id為1的行的修改就對其他事務可見了。但是事務1在此前已經從這行讀到了另外一個“age”的值。在可序列化 (SERIALIZABLE)和可重復讀(REPEATABLE READS)的隔離級別,數據庫在第二次SELECT請求的時候應該返回事務2更新之前的值。在授權讀(READ COMMITTED)和未授權讀(READ UNCOMMITTED),返回的是更新之后的值,這個現象就是不可重復讀(non-repeatableread)。
有兩種策略可以避免不可重復讀(non-repeatable read)。一個是要求事務2延遲到事務1提交或者回滾之后再執行。這種方式實現了T1,T2 的串行化調度。串行化調度可以支持可重復讀(repeatablereads)。
另一種策略是多版本并發控制。為了得到更好的并發性能,允許事務2先提交。但因為事務1在事務2之前開始,事務1必須在其開始執行時間點的數據庫的快照上面操作。當事務1最終提交時候,數據庫會檢查其結果是否等價于T1, T2串行調度。如果等價,則允許事務1提交,如果不等價,事務1需要回滾并拋出個串行化失敗的錯誤。
使用基于鎖的并發控制,在可重復讀(REPEATABLE READS)的隔離級別中,ID=1的行會被鎖住,在事務1提交或回滾前一直阻塞語句2的執行。在授權讀(READ COMMITTED)的級別,語句1第二次執行,age已經被修改了。
在多版本并發控制機制下,可序列化(SERIALIZABLE)級別,兩次SELECT語句讀到的數據都是事務1開始的快照,因此返回同樣的數據。但是,如果事務1試圖UPDATE這行數據,事務1會被要求回滾并拋出一個串行化失敗的錯誤。
在授權讀(READ COMMITTED)隔離級別,每個語句讀到的是語句執行前的快照,因此讀到更新前后不同的值。在這種級別不會有串行化的錯誤(因為這種級別不要求串行化),事務1也不要求重試。
幻影讀(phantom read)
在事務執行過程中,當兩個完全相同的查詢語句執行得到不同的結果集。這種現象稱為“幻影讀(phantom read)”
當事務沒有獲取范圍鎖的情況下執行SELECT ... WHERE操作可能會發生“幻影讀(phantom read)”。
“幻影讀(phantom read)”是不可重復讀(Non-repeatable reads)的一種特殊場景:當事務1兩次執行SELECT ... WHERE檢索一定范圍內數據的操作中間,事務2在這個表中創建了(如INSERT)了一行新數據,這條新數據正好滿足事務1的“WHERE”子句。
事務 1 |
事務 2 |
/* Query 1 */ SELECT * FROM users WHERE age BETWEEN 10 AND 30; |
|
/* Query 2 */ INSERT INTO users VALUES ( 3, 'Bob', 27 ); COMMIT; |
|
/* Query 1 */ SELECT * FROM users WHERE age BETWEEN 10 AND 30; |
需要指出的是事務1執行了兩遍同樣的查詢語句。如果設了最高的隔離級別,兩次會得到同樣的結果集,這也正是可數據庫在序列化(SERIALIZABLE)隔離級別上需要滿足的。但是在較低的隔離級別上,第二次查詢可能會得到不同的結果集。
在可序列化(SERIALIZABLE)隔離級別,查詢語句1在age從10到30的記錄上加鎖,事務2只能阻塞直至事務1提交。在可重復讀(REPEATABLEREAD)級別,這個范圍不會被鎖定,允許記錄插入,因此第二次執行語句1的結果中會包括新插入的行。
隔離級別、讀現象和鎖(Isolation Levels, ReadPhenomena and Locks)
隔離級別vs讀現象(IsolationLevels vs Read Phenomena)
隔離級別 |
臟讀 |
不可重復讀 |
幻影讀 |
未授權讀 |
可能發生 |
可能發生 |
可能發生 |
授權讀 |
- |
可能發生 |
可能發生 |
可重復讀 |
- |
- |
可能發生 |
可序列化 |
- |
- |
- |
可序列化(Serializable)隔離級別不等同于可串行化(Serializable)。可串行化調度(Serializable)是避免以上三種現象的必要條件,但不是充分條件。
“可能發生”表示這個隔離級別會發生對應的現象,“-”表示不會發生。
隔離級別vs 鎖持續時間(IsolationLevels vs Lock Duration)
在基于鎖的并發控制中,隔離級別決定了鎖的持有時間。"C"-表示鎖會持續到事務提交。 "S" –表示鎖持續到當前語句執行完畢。如果鎖在語句執行完畢就釋放則另外一個事務就可以在這個事務提交前修改鎖定的數據,從而造成混亂。
隔離級別l |
寫操作 |
讀操作 |
范圍操作 (...where...) |
未授權讀 |
S |
S |
S |
授權讀 |
C |
S |
S |
可重復讀 |
C |
C |
S |
可序列化 |
C |
C |
C |
參照
相關條目
原子性一致性持久性鎖樂觀并發控制關系數據庫快照隔離
外部鏈接
Oracle? Database Concepts,chapter 13 Data Concurrency and Consistency, Preventable Phenomena and Transaction Isolation LevelsOracle? Database SQL Reference,chapter 19 SQL Statements: SAVEPOINT to UPDATE,SET TRANSACTIONin JDBC: Connection constant fields, Connection.getTransactionIsolation(), Connection.setTransactionIsolation(int)in Spring Framework: @Transactional, Isolation
Categories:
Data managementTransaction processing
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com