數據庫是一個併發操做的環境,就像多線程同樣,這樣在高併發的狀況下回出現一些問題。html
假設咱們有一張表Account,表結構和數據以下所示數據庫
AccountName | Balance |
jo | 100 |
fo | 200 |
假設咱們有兩個事事務(T1,T2)多線程
髒讀:當一個事務容許讀取另一個事務修改但未提交的數據時,就可能發生髒讀(dirty reads)。併發
(1)T1更新jo的餘額:高併發
UPDATE Account SET Balance=500 WHERE AccountName='jo'
(2)T2選出jo的餘額:spa
SELECT Balance FROM Account WHERE AccountName='jo'
(3)T1回滾(rollback)。線程
此時在(2)中已經選出了500這個值,儘管最後T1的回滾讓jo的餘額保持100沒有改變,這種狀況就是髒讀。code
不可重複讀:在一次事務中,當一行數據獲取兩遍獲得不一樣的結果表示發生了"不可重複讀(non-repeatable read)"。htm
(1)T2選出jo的餘額:對象
SELECT Balance FROM Account WHERE AccountName='jo'
(2)T1中更新jo的餘額而且提交(commit)。
UPDATE Account SET Balance=500 WHERE AccountName='jo' Commit Tran
(3)T2再次選出jo的餘額
SELECT Balance FROM Account WHERE AccountName='jo'
此時在(1)中選出的餘額是100,在(3)中選出的餘額是500,在同一個事務T2中兩個Select獲得了不同的數據。
幻讀:在事務執行過程當中,當兩個徹底相同的查詢語句執行獲得不一樣的結果集。這種現象稱爲「幻讀(phantom read)」
(1)T2選擇金額大於100的帳戶餘額
SELECT Balance FROM Account WHERE Balance>100
(2)T1插入新的餘額大於100的帳戶
INSERT INTO Account (AccountName,Balance) VALUES ('ho',300)
(3)T2中再次選擇金額大於100的帳戶
SELECT Balance FROM Account WHERE Balance>100
此時(1)讀出了一條數據,(2)讀出了兩條數據,同一個查詢的在同一個事務中的兩次讀取獲得了不一樣的數量的結果集,這種現象就是幻讀。
爲了處理以上併發問題,有了併發控制的概念。簡單來講就是一個事務在執行的時候,經過對正在訪問的資源加鎖來阻塞其餘事務對資源的操做。
不一樣的加鎖方式對應不一樣的隔離級別,用來針對不一樣的併發問題。
READ UNCOMMITTED
事務執行期間,對任何操做不加鎖。意味着能夠讀取其餘事務未提交的更新。這個隔離級別下以上的併發問題都有可能發生。
READ COMMITTED
事務執行期間,對寫操做加鎖。意味着當前將要寫入的數據加了寫鎖,阻塞其餘事務讀取或者更改加鎖數據,直到事務結束。
這個隔離級別能夠防止其餘的事務髒讀,由於其餘的事務對加鎖數據的讀寫操做都被當前事務阻塞了。不過因爲當前事務沒有加讀鎖,因此當前事務會發生不可重複讀。
REPEATABLE READ
事務執行期間,對讀,寫操做加鎖。意味着當前事務寫入和讀取的數據其餘的事務都沒法訪問,知道當前事務結束(回滾,或者提交),當前事務不會發生不可重複讀,不過因爲當前讀取的數據範圍沒有加鎖,其餘的事務能夠插入知足當前事務讀取範圍過濾條件的數據;或者更新當前事務讀取範圍外的數據,已使其知足當前事務的讀取範圍過濾條件。這樣就會形成幻讀。
SERIALIZABLE
可序列化或者叫可串行化,按照字面意思,是事務只能一個接着一個的執行。
實際的實現方式是經過加讀鎖,寫鎖和範圍鎖來保證事務執行的串行化。意味着在當前事務的執行過程當中,會阻塞其餘的涉及當前事務相關數據及數據範圍的事務。
本文只是一個簡單的介紹,要徹底的理解隔離級別,而且推斷出事務在不一樣隔離級別下會有什麼樣的不一樣就要深刻的瞭解SQL Server在不一樣隔離級別下對不一樣對象的鎖定,以及不一樣的鎖之間是如何交互的,這些方面的問題推薦下面這篇博客:
http://www.cnblogs.com/RicCC/archive/2010/03/05/transaction-lock-isolation-level.html