併發構架
當許多人試圖同時修改數據庫內的數據時,必須執行控制系統以使某個人所做的修改不會對他人產生負面影響。這稱爲併發控制。
併發控制理論因創立併發控制的方法不同而分爲兩類:
悲觀併發控制
鎖定系統阻止用戶以影響其它用戶的方式修改數據。如果用戶執行的操作導致應用了某個鎖,則直到這個鎖的所有者釋放該鎖,其它用戶才能
執行與該鎖衝突的操作。該方法主要用在數據爭奪激烈的環境中,以及出現併發衝突時用鎖保護數據的成本比回滾事務的成本低的環境中,因
此稱該方法爲悲觀併發控制。
樂觀併發控制
在樂觀併發控制中,用戶讀數據時不鎖定數據。在執行更新時,系統進行檢查,查看另一個用戶讀過數據後是否更改了數據。如果另一個用戶
更新了數據,將產生一個錯誤。一般情況下,接收錯誤信息的用戶將回滾事務並重新開始。該方法主要用在數據爭奪少的環境內,以及偶爾回
滾事務的成本超過讀數據時鎖定數據的成本的環境內,因此稱該方法爲樂觀併發控制。
Microsoft® SQL Server™ 2000 支持廣泛的樂觀和悲觀併發控制機制。通過指定下列各項,用戶可以指定併發控制類型:
用於連接的事務隔離級別。
根據以上描述主要是通過數據爭奪的激烈程度、數據保護成本來選擇併發控制方式。當我們選擇不同的併發控制方式,隨即產生併發問題。
併發問題
如果沒有鎖定且多個用戶同時訪問一個數據庫,則當他們的事務同時使用相同的數據時可能會發生問題。併發問題包括:
丟失或覆蓋更新。
未確認的相關性(髒讀)。
不一致的分析(非重複讀)。
幻像讀。
丟失更新
當兩個或多個事務選擇同一行,然後基於最初選定的值更新該行時,會發生丟失更新問題。每個事務都不知道其它事務的存在。最後的更新將
重寫由其它事務所做的更新,這將導致數據丟失。
例如,兩個編輯人員製作了同一文檔的電子複本。每個編輯人員獨立地更改其複本,然後保存更改後的複本,這樣就覆蓋了原始文檔。最後保
存其更改複本的編輯人員覆蓋了第一個編輯人員所做的更改。如果在第一個編輯人員完成之後第二個編輯人員才能進行更改,則可以避免該問
題。
未確認的相關性(髒讀)
當第二個事務選擇其它事務正在更新的行時,會發生未確認的相關性問題。第二個事務正在讀取的數據還沒有確認並且可能由更新此行的事務
所更改。
例如,一個編輯人員正在更改電子文檔。在更改過程中,另一個編輯人員複製了該文檔(該複本包含到目前爲止所做的全部更改)並將其分發
給預期的用戶。此後,第一個編輯人員認爲目前所做的更改是錯誤的,於是刪除了所做的編輯並保存了文檔。分發給用戶的文檔包含不再存在
的編輯內容,並且這些編輯內容應認爲從未存在過。如果在第一個編輯人員確定最終更改前任何人都不能讀取更改的文檔,則可以避免該問題
。
不一致的分析(非重複讀)
當第二個事務多次訪問同一行而且每次讀取不同的數據時,會發生不一致的分析問題。不一致的分析與未確認的相關性類似,因爲其它事務也
是正在更改第二個事務正在讀取的數據。然而,在不一致的分析中,第二個事務讀取的數據是由已進行了更改的事務提交的。而且,不一致的
分析涉及多次(兩次或更多)讀取同一行,而且每次信息都由其它事務更改;因而該行被非重複讀取。
例如,一個編輯人員兩次讀取同一文檔,但在兩次讀取之間,作者重寫了該文檔。當編輯人員第二次讀取文檔時,文檔已更改。原始讀取不可
重複。如果只有在作者全部完成編寫後編輯人員纔可以讀取文檔,則可以避免該問題。
幻像讀
當對某行執行插入或刪除操作,而該行屬於某個事務正在讀取的行的範圍時,會發生幻像讀問題。事務第一次讀的行範圍顯示出其中一行已不
復存在於第二次讀或後續讀中,因爲該行已被其它事務刪除。同樣,由於其它事務的插入操作,事務的第二次或後續讀顯示有一行已不存在於
原始讀中。
例如,一個編輯人員更改作者提交的文檔,但當生產部門將其更改內容合併到該文檔的主複本時,發現作者已將未編輯的新材料添加到該文檔
中。如果在編輯人員和生產部門完成對原始文檔的處理之前,任何人都不能將新材料添加到文檔中,則可以避免該問題。
併發問題對數據庫進行讀取、更新、刪除和插入數據過程中得到不同的結果進行歸類。假設用戶在某一段時間內要求操作數據的正確性和一致
性。
更新、插入 -- 髒讀
更新 -- 非重複讀
刪除、插入 -- 幻像讀
爲了處理併發問題,可以採用適當的事務隔離級別進行控制。
SET TRANSACTION ISOLATION LEVEL
控制由連接發出的所有 Microsoft® SQL Server™ SELECT 語句的默認事務鎖定行爲。
語法
SET TRANSACTION ISOLATION LEVEL
{ READ COMMITTED
| READ UNCOMMITTED
| REPEATABLE READ
| SERIALIZABLE
}
參數
READ COMMITTED
指定在讀取數據時控制共享鎖以避免髒讀,但數據可在事務結束前更改,從而產生不可重複讀取或幻像數據。該選項是 SQL Server 的默認值
。
READ UNCOMMITTED
執行髒讀或 0 級隔離鎖定,這表示不發出共享鎖,也不接受排它鎖。當設置該選項時,可以對數據執行未提交讀或髒讀;在事務結束前可以更
改數據內的數值,行也可以出現在數據集中或從數據集消失。該選項的作用與在事務內所有語句中的所有表上設置 NOLOCK 相同。這是四個隔
離級別中限制最小的級別。
REPEATABLE READ
鎖定查詢中使用的所有數據以防止其他用戶更新數據,但是其他用戶可以將新的幻像行插入數據集,且幻像行包括在當前事務的後續讀取中。
因爲併發低於默認隔離級別,所以應只在必要時才使用該選項。
SERIALIZABLE
在數據集上放置一個範圍鎖,以防止其他用戶在事務完成之前更新數據集或將行插入數據集內。這是四個隔離級別中限制最大的級別。因爲並
發級別較低,所以應只在必要時才使用該選項。該選項的作用與在事務內所有 SELECT 語句中的所有表上設置 HOLDLOCK 相同。
註釋
一次只能設置這些選項中的一個,而且設置的選項將一直對那個連接保持有效,直到顯式更改該選項爲止。這是默認行爲,除非在語句的 FROM
子句中在表級上指定優化選項。
SET TRANSACTION ISOLATION LEVEL 的設置是在執行或運行時設置,而不是在分析時設置。
READ COMMITTED -- 避免髒讀
READ UNCOMMITTED -- 不控制
REPEATABLE READ -- 避免不可重複讀
SERIALIZABLE -- 避免幻像讀