1 概述 1 概述 本篇文章簡要對事物與鎖的分析比較詳細,因此就轉載了。 2 具體內容 2 具體內容 併發可以定義為多個進程同時訪問或修改共用數據的能力。處於活動狀態而互不幹涉的併發用戶進程的數量越多,資料庫系統的併發性就越好。當一個正在修改數據的進程阻止了其他進程讀取該數據,或者當一個正在讀取數據 ...
1 概述
本篇文章簡要對事物與鎖的分析比較詳細,因此就轉載了。
2 具體內容
併發可以定義為多個進程同時訪問或修改共用數據的能力。處於活動狀態而互不幹涉的併發用戶進程的數量越多,資料庫系統的併發性就越好。當一個正在修改數據的進程阻止了其他進程讀取該數據,或者當一個正在讀取數據的進程阻止了其他進程修改該數據,併發性就降低了。本文用術語“讀取”或者“訪問”描述數據上的SELECT操作,用“寫入”或“修改”描述數據上的INSERT,UPDATE以及DELETE操作。
一般地,資料庫系統可以採用兩種方式來管理併發數據訪問,樂觀併發控制和悲觀併發控制。
併發控制模型
對於任何一種併發控制模式,如果兩個事務試圖同一時刻修改數據的話都會產生衝突。這兩種模式之間的區別在於,是在衝突發生前進行防止,還是發生後採取某種方法來處理衝突。
悲觀併發控制
對於悲觀併發控制,該模型假定系統中存在足夠多的數據修改操作,以致於事務的任何數據讀取/修改操作都可能受到其他事務數據修改操作的影響,即假定衝突總是會發生的。SQL Server預設通過鎖(lock)來保證讀者和寫者之間的互斥。樂觀併發控制
對於樂觀併發控制,該模型假定系統中存在非常少的相互衝突的數據修改操作,以致任何單獨的事務都不太可能修改其它事務正在修改的數據。樂觀併發控制預設採用行版本控制來處理併發。
例如,在讀取數據時我們會得到一個數據的版本version 1,當需要修改數據時,我們先檢查數據的版本是不是version 1,如果是就修改數據;如果不是,就說明在當前事務的讀操作和寫操作之間已經有別的事務對數據進行了修改(每次修改操作都會使得數據的版本+1),SQL Server將會產生一個錯誤消息,由上層應用程式響應此錯誤。
事務處理
無論是採用哪種併發控制模型,對於事務的理解是至關重要的。事務是SQL Server中任務的基本單位。典型地,它由幾個讀取和修改數據的SQL命令組成,但是直到COMMIT命令被執行以後,修改操作才被認為是終結了。ACID屬性
原子性(Atomicity)
SQL Server保證事務的原子性。原子性指的是每個事務要麼全部執行,要麼什麼都不執行。也就是說,如果一個事務提交了,它造成的所有效果都會被保留。如果中止了,其所有效果都會被撤銷。
一致性(Consistency)
一致性屬性確保事務不允許系統到達一個不准確的邏輯狀態——數據必須總是保持邏輯上的正確。即使在發生系統故障時,約束和規則必須得到保證。(一致性一般被原子性、隔離性以及持久性所涵蓋,並且概念上會產生重覆)
隔離性(Isolation)
隔離性會將併發事務與其他併發事務的更新操作分隔開。當該事務正在執行時,其他事務是無法看到進行中的任務的。SQL Server會在事務之間自動實現隔離。它採用鎖定數據或者行版本使得多個併發事務能夠併發操作數據,以防止導致不正確結果。
隔離性意味著事務必須在不幹擾其他事務的前提下獨立執行。換言之,在事務執行完畢之前,其所訪問的數據不能受系統其他部分的影響。
持久性(Durability)
當事務提交之後,SQL Server的持久性屬性就會確保該事務的作用持續存在(即使發生系統故障)。如果在事務進行過程中發生系統故障,事務就會被完全撤銷,不會在數據上遺留部分作用。如果在事務的提交確認被髮送到調用的程式之後立刻發生故障,資料庫會確保該事務的存在。預寫式日誌以及SQL Server啟動恢復階段的事務自動回滾/自動重做機制能夠確保持久性。
一致性問題
事務總是全部支持ACID屬性的。事務可能還會表現出一些另外的行為,稱為“一致性問題”,而我並不認為它們是“問題”。它們僅僅是可能存在的行為,而用戶能夠決定允許哪些和阻止哪些,用戶對於隔離級別的選擇決定了下列這些行為中哪些是被允許的。丟失更新
當兩個事務讀取相同數據並且都處理該數據(修改了它的值),然後都嘗試更新原來的數據成新的值時,這種行為就會發生了。第二個事務可能完全覆蓋掉第一個所完成的更新。時間 | 取款事務A | 取款事務B |
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢賬戶餘額為1000 | |
T4 | 查詢賬戶餘額為1000 | |
T5 | 取出100,存款餘額為900 | |
T6 | 取出300,存款餘額為700 | |
T7 | 提交事務 | |
T8 | 提交事務 |
最終賬戶餘額為900,取款事務A的更新丟失了。丟失更新是這些行為中唯一一個用戶可能在所有情況下都想避免的行為。
臟讀
這種行為在一個事務讀取未提交數據時會發生,如果一個事務修改了數據但是尚未提交修改,而另一個正在讀取數據的事務會讀到這個修改從而導致一種不一致的狀態發生。時間 | 查詢事務A | 取款事務B |
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢賬戶餘額為1000 | |
T4 | 取出100,存款餘額為900 | |
T5 | 查詢賬戶餘額為900 | |
T6 | 撤銷事務,恢復為1000 | |
T7 | 提交事務 |
查詢事務A讀取到取款事務B還未提交的餘額900。
預設情況下,臟讀是不允許的。謹記:更新數據的事務是無法控制別的事務在它提交之前讀取其數據的,這是由讀取數據的事務來決定是否想要讀取未必會被提交的數據。
不可重覆讀
這種行為又被稱為“不一致分析”。如果同一事務分別以兩個讀操作讀取相同資源時,可能會得到不同的值,這就是不可重覆讀。時間 | 查詢事務A | 取款事務B |
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢賬戶餘額為1000 | |
T4 | 取出100,存款餘額為900 | |
T5 | 查詢賬戶餘額為900 | |
T6 | 提交事務 | |
T7 | 提交事務 |
查詢事務A兩次讀取餘額獲取到不同結果。
幻讀
這種行為產生於一個數據集內的部分數據被修改時。如果事務A讀取與搜索條件相匹配的若幹行。事務B以插入或刪除行等方式來修改事務A的結果集,然後再提交。時間 | 取款記錄處理事務A | 取款事務B |
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢到5條取款記錄 | |
T4 | 查詢餘額為1000元 | |
T5 | 取出100,存款餘額為900 | |
T6 | 查詢到6條取款記錄 | |
T7 | 提交事務 | |
T8 | 提交事務 |
對於取款記錄處理事務A,兩次查詢的結果集不同。
事務的行為取決於隔離級別,也就是決定上述四種行為中那些是被允許的。併發控制模型決定了隔離級別是如何實現的——或者更明確的講,決定了SQL Sever是如何確保用戶所不想要的行為不發生的。隔離級別
SQL Server支持五種隔離級別來控制讀操作的行為。其中三個只在悲觀併發模型中可用,一個只在樂觀併發模型中可用。剩下的一個在兩個模式下都是可用的。
未提交讀
除了丟失更新以外,上面提到的其他行為都可能發生。未提交讀是通過使讀操作不占用任何鎖來實現的,當前事務能夠讀取其他事務已經修改過但是尚未提交的數據。
當採用未提交讀時,用戶是放棄了對高一致性數據的把握而趨向於支持系統的高併發能力,使用戶不會再互相鎖定對方。那麼,何時才應該選擇未提交讀呢?顯然,每筆數據都須保證平衡的金融交易是不適合的。而對於某些決策支持分析來說可能會很適合(譬如,需要察看銷售走勢時),因為完全沒有必要做到完全精確而且會帶來併發性能的提升,因此是相當值得的。
已提交讀
已提交讀是資料庫引擎的預設級別。SQL Server 2005支持兩種已提交讀的隔離級別,這種隔離級別既可以是樂觀的也可以是悲觀的,預設採用悲觀併發控制。為了區分,悲觀實現稱“已提交讀(鎖定)”,樂觀實現稱為”已提交讀(快照)”。
已提交讀隔離級別保證了一個操作不會讀到別的程式已經修改但是尚未提交的數據。如果別的事務正在更新數據並因此在數據行上持有排它鎖,當前的事務就必須等待這些鎖釋放後才能使用這個數據(無論是讀取還是修改)。同樣地,事務必須至少在要被訪問的數據上加上共用鎖,其他事務可以讀取數據但是不能修改數據。預設,共用鎖在數據讀取過後就被釋放掉,而無需在事務的持續時間內保留。
已提交讀(快照),也能保證一個操作不會讀到未提交數據,但不是通過迫使其他進程等待的方式。對於已提交讀(快照),每當一行數據被修改後,SQL Server就會生成該行數據前一次已提交值的一個版本(version),被修改的數據仍舊被鎖定著,但是其他進程可以看到該數據在更新操作開始之前的版本。
可重覆讀
可重覆讀是一種悲觀的隔離級別。它在已提交讀的基礎上增加了新的屬性:確保當事務重新訪問數據或查詢被再一次執行時,數據將不再發生改變。換句話說,在一個事務中執行相同的查詢兩次是不會看到由其他事務所造成的任何數據的改變的。然而,可重覆讀隔離級別還是允許幻讀的出現。
在某些情況下,防止不可重覆讀是用戶嚮往的一種安全措施。但是世上沒有免費的午餐,這種額外的措施所帶來的開銷是事務中所有的共用鎖必須保留到事務完成為止。
排它鎖必須總是保留到事務結束為止,無論採用何種隔離級別或者併發模型,這樣事務才能在需要時被回滾。如果鎖提前釋放了,就不太可能完成撤銷操作,因為其他併發事務可能已經使用了同一數據,並且修改了它的值。
只要事務是打開的,沒有其他用戶可以修改被該事務所訪問的數據。顯然這會嚴重降低併發性和性能。因此,如果事務不保持簡短或者編寫應用程式時沒有能夠註意到這樣潛在的鎖競爭問題,將會導致大量的事務因為等待鎖釋放而掛起。
快照
快照隔離是一種樂觀隔離級別,類似於已提交讀(快照),如果當前版本被鎖定住時,它允許其他事務讀取已提交數據的早期版本。快照隔離和已提交讀(快照)的區別與(早期版本該有多早、保留多少個早期版本)這個問題相關,我們在行版本控制小節中詳述。儘管快照隔離所避免的行為和可串列化所避免的是相同的,但是快照隔離並不是真正意義上的可串列化隔離級別。對於快照隔離,可能會有兩個個事務同時執行,並引起一個任何序列化執行都不可能產生的結果。
如果兩個事務並行地運行,最終會交換titles表裡兩本書的價格。然而,不存在一種序列化執行的方式最終導致數值的交換。無論是先執行事務1然後執行事務2,還是先執行事務2再執行事務1,任何序列順序最終將導致兩本書擁有相同的價格。可串列化
可串列化也是一種悲觀隔離級別。可串列化隔離級別在可重覆讀的基礎上增加了新的屬性:確保在重新執行查詢時,SQL Server不會在中間的過渡期增加新的行。換句話說,如果同一事物在相同的查詢被執行兩次的話,幻讀不會出現。可串列化也因此成為最健壯的悲觀隔離級別,因為防止了之前所描述的所有可能的“不一致問題“。
額外的安全措施必定會帶來額外的開銷。可串列化隔離級別下,事務中的所有共用鎖都必須保留到事務完成為止。另外,執行可串列化隔離級別不僅需要鎖定已讀數據,還需要鎖定那些不存在的數據,參看後面的鍵範圍鎖。
鎖定
對於多用戶資料庫系統而言,鎖定是一個至關重要的功能。鎖在悲觀和樂觀併發控制模型中都有所應用,儘管在每種模型中其他事務處理“被鎖定數據”的方式是不同的。在悲觀模型中,寫者總是阻塞讀者和寫者,而讀者也會阻塞寫者。對於樂觀模型,唯一可能發生的阻塞是寫者阻塞其他寫者。鎖定的基本概念
SQL Server可以使用幾種不同方式來鎖定數據,舉例來說,讀操作獲取共用鎖而寫操作獲取排他鎖。更新鎖在更新操作的開頭部分獲取。SQL Server會自動獲取並釋放所有這些類型的鎖。它還負責管理鎖定模式之間的相容性,解決死鎖問題,併在需要的時候進行鎖升級。它在表、表的分頁、索引鍵以及單獨的數據行上支配鎖。
鎖定類型
共用鎖
當數據被讀取時,SQL Server自動獲取共用鎖。許多事務可以在同一數據上都持有共用鎖,但是沒有事務可以在已經有一個共用鎖存在的情況下,在該數據上再獲取一個排他鎖。一般的,當數據已經讀取完畢後,共用受就會立即釋放掉,但是可以通過使用查詢提示或者採用不同的事務隔離級別來改變這種預設方式。排它鎖
當數據被插入、更新或者刪除操作修改以後,SQL Server就會自動獲取數據上的排他鎖。一次只能有一個事務持有特定數據資源上的排它鎖。排它鎖會保留到事務結束為止。這就意味著被修改的數據通常在當前事務提交或者回滾之前對其他事務來說是不可用的。其他事務可以通過使用查詢提示來讀取被排它鎖鎖定的數據。更新鎖
更新鎖實際上並不是一種獨立的鎖,他是共用鎖和排他鎖的一種混合。當SQL Server執行一個數據修改操作但是首先需要搜索表以尋找到被修改的資源時,更新鎖就會被獲取。更新鎖能夠預防鎖升級而產生的死鎖,SQL Server保證更新鎖的持有者能夠將其轉化成排他鎖,死鎖就可以避免了。更新鎖本身不足以使用戶能夠修改數據——所有的數據修改都要求被修改的數據資源上存在一個排它鎖。只要有一個事務對資源持有更新鎖,其它事務就無法獲取該資源的更新鎖或者排他鎖了。持有更新鎖的事務能夠將其轉換成該資源上的排它鎖,因為更新鎖避免了與其他進程之間的鎖的不相容。可以將更新鎖看作是“意圖更新鎖”,這才是它實際所扮演的角色。更新鎖會保留到事務結束或者當它轉換成排他鎖。
不要被鎖的名字誤導,更新鎖並不只是針對更新操作而設計的。SQL Server使用更新鎖適用於任何需要進行實際修改之前搜索數據的數據修改操作。這樣的操作包括受限更新及刪除,也包括在帶有聚集索引的表上進行的插入操作。對於後面一種情況,SQL Server必須先搜索數據(使用聚集索引)以找到正確的位置來插入新的記錄。當SQL Server只進行到搜索階段時,它會採用更新鎖來保護數據,而只有當它找到正確的位置並開始插入以後才將更新鎖升級為排他鎖。
意向鎖
意向鎖實際上並不是一種獨立的鎖定模式。你可以擁有意向共用鎖,意向排他鎖甚至意向更新鎖。由於SQL Server可以在不同級別的粒度上獲取鎖,因此需要一種機制來指出一個資源上的組件已經被鎖定了。例如,如果一個事務試圖鎖定一張表,SQL Server需要採用一種機制來判斷是否這張表上的行(或者一個分頁)已經被鎖住了。意向鎖就是起這個作用,在瞭解鎖的粒度時會深入研究意向鎖。鍵範圍鎖
只在可串列化隔離級別中為了鎖定一定範圍內的數據而被獲取。共用鎖和排它鎖可以在表、分頁、行或者鍵上獲取,而鍵鎖只能從鍵上獲取。鎖的粒度
SQL Server可以鎖定表、分頁、行等級別的數據資源。它同樣可以鎖定索引鍵及一定範圍內的索引鍵。謹記如果表上存在聚集索引,數據行就在聚集索引的葉級,並且是由鍵鎖而不是行鎖來鎖定它們的。 SQL Server對每個鎖都進行追蹤並且包含了鎖、被鎖定資源(行、鍵或分頁)、鎖的模式以及特定資源的一個標識符。當一個事務申請鎖時,SQL Server會將所申請的鎖與已經申請的鎖進行比較並尋找完全匹配資源類型以及標識符的鎖。但是,如果一個事務在表中的某行上占有一個排他鎖,別的事務可能會嘗試在整張表上獲取一個鎖。 由於是兩種不同的資源,SQL Server不會找到一個完全的匹配,這就需要使用意向鎖了。SQL Server會記錄在表的一行記錄上擁有排他鎖的事務也在包含該行記錄的分頁上占有一個意向鎖,以及在包含該行記錄的這張表上擁有一個意向鎖。當其他事務試圖獲取這張表上的一個排他鎖時,其他事務將會被阻塞。鍵鎖
SQL Server支持兩種類型的鍵鎖,而它採用哪種類型則取決於當前事務的隔離級別。如果隔離級別是已經提交讀、可重覆讀或者快照,SQL Server會在處理查詢時嘗試鎖定實際被訪問的索引鍵。對於聚集索引的表而言,數據行就是索引的葉級別,而用戶可以看到所獲取的鍵鎖。如果表是堆結構的話,用戶可能會看到非聚集索引上的鍵鎖以及實際數據上的行鎖。
如果隔離級別是可串列化,情況就有所不同了。為了防止幻讀,如果一個事務中掃描了一個範圍內的數據就需要充分鎖定住該表以確保沒人能夠插入新值到已掃描的範圍內。在SQL Server早期版本中是通過鎖定整個分頁甚至整張表來保證這一點的。在許多情況下,這可能導致了更大範圍的數據被鎖定住了,造成了不必要的資源競爭。SQL Server 2005採用了一種稱為“鍵範圍鎖”的單獨鎖模式,與索引中的特定鍵值相關聯並表明在索引中這兩個鍵之間的所有值被鎖定住了。
鎖的相容性
鎖簡稱
簡單相容性矩陣
完整相容性矩陣
行級鎖定VS分頁鎖定
鎖粒度越小,加鎖操作越頻繁,管理鎖帶來的開銷就越大。但是,鎖粒度越小,衝突率越小,併發性能會更好。每種類型的鎖定在針對不同類型的程式和處理方法時都會顯示出其獨特的優勢,因此選中那種類型的鎖定,取決於應用程式和數據。鎖升級
SQL Server在適當的時候會自動將行、鍵或者分頁級鎖升級為粒度更粗的表級鎖。這種升級保護了系統資源(防止系統使用太多的記憶體在追蹤鎖),並且提高了效率。例如,在一個查詢獲取許多行級鎖後,鎖級別可以升級為表級鎖,因為這時獲取並持有一個單獨的表級鎖比持有許多行級鎖可能更有意義。死鎖
當兩個事務都在等待獲取資源,但是由於相互阻礙對方獲取資源導致沒有事務能夠前進時就會發生死鎖。行級版本控制
樂觀併發控制採用了一種稱為行版本控制的新技術來保障事務。在使用樂觀鎖併發控制時會獲取排他鎖。樂觀併發和悲觀併發的區別在於樂觀併發中寫操作與讀操作之間不會互相阻塞。換句話說就是,當被請求資源當前擁有共用鎖時,申請排它鎖的事務不會被阻塞,相反,當被請求資源當前擁有排他鎖時,申請共用鎖的進程也不會被阻塞。
一旦啟用樂觀並反控制,SQL Server就使用tempdb資料庫來存儲所有已經修改過的記錄的副本,並且只要存在來自任意事務的訪問需求,就會繼續維持這些副本。當tempdb用來存儲被修改記錄的早期版本時,就其稱為版本存儲區。
行版本控制的實現
SQL Server引入了一種新的隔離級別:快照隔離以及一種新式的無阻塞風格的已提交讀隔離——已提交讀(快照)。這些基於版本控制的隔離級別允許讀者獲取行的一個先前已提交過的值而不會產生阻塞,這樣就提高了系統的併發能力。為了使它起作用,SQL Server必須在行被修改或刪除時保留舊版本的記錄。如果在同一行上進行多次更新,SQL Server就可能需要維護該行的多個早起版本。鑒於此,行版本控制有時也被稱為多版併發控制。
當表或索引中的一行數據被更新時,SQL Server會用執行更新的那個事務的事務序列號來標記新的行。事務序列號是一個單調遞增的數字,在每個SQL Server的實例中保證唯一。在更新一行數據時,之前的版本存放在版本存儲區內,而新的行包含一個指向版本存儲區中舊的行數據的指針。版本存儲區里舊的行數據可能包含了指向更早版本的指針。一條行記錄的所有版本串接成一個鏈表。SQL Server可能需要沿著鏈表中的幾個指針才能到達一個正確的版本,只要有操作需要引用它們,行的版本就必須在版本存儲區內保存。
在應用程式使用預設的悲觀模型造成的併發性下降而不能令人滿意時,SQL Server可以改用樂觀併發控制模型。在切換到基於樂觀版本控制的隔離級別之前,用戶必須仔細權衡使用新型併發模型的效果。處理需要額外的管理來為版本存儲區監控tempdb以外,鑒於維護舊版本鎖帶來的額外工作量,版本控制還會降低更新操作的性能。即使當前沒有人在讀取數據,更新操作也得為此買單。如果有使用行版本控制的讀操作,它們必須花費額外的開銷來遍歷鏈表指針,以找到需要的行數據的合適版本。
另外,由於快照隔離的樂觀併發模型假定系統不會發生很多的更新衝突,如果用戶預見到在同一數據上的併發更新會產生競爭,就不應該選擇快照隔離級別。快照隔離級別能夠使讀者不被寫者阻塞,但是併發的寫者仍然不被允許。在預設的悲觀模型中,第一個寫者會阻塞所有的後續寫者,但如果採用快照隔離,後續寫者實際上會接受到錯誤消息且應用程式需要重新提交初始請求。
基於快照的隔離級別
已提交讀快照隔離(RCSI)
已提交讀快照隔離是一種語句級的快照隔離,也就是任何查詢都能看到在語句開始那一刻最近提交過的數值。假設在啟用了RCSI的資料庫上有如下兩個事務,且在事務開始運行之前Product 922的ListPrice值是8.89
註意當時間為2時,事務1所作出的修改尚未提交,因此Product ID=922的行上仍然持有鎖。但是事務2不會被這個鎖阻塞住,它能夠訪問該行數據上一次已提交的ListPrice值8.89。這仍然屬於已提交讀隔離級別(一個無阻塞的變種),所以不能防止“不可重覆讀”。
RCSI最大的益處是可以引入更好的併發性,因為讀者與寫者之間不會相互阻塞。但是寫者之間還是會發生阻塞,因此標準的加鎖機制適用於全部的更新、刪除和插入操作。
快照隔離(SI)
SI提供了數據的一種事務一致性視圖。任何讀取操作都將得到在事務開始那一刻最近已提交過的數據版本(對於RCSI,會得到在語句開始那一刻最近已提交過的數據版本)。需要謹記的一個要點:事務並不是從BEGIN TRAN語句開始的,對於SI來說,事務是在第一次訪問資料庫內任意數據的時候才開始的。 儘管事務1已經提交了,事務2繼續返回它讀到的初始值8.99,直到事務2完成為止。只有在事務2完成以後,該鏈接才能讀到ListPrice的新值。更新衝突
兩種樂觀併發級別之間的重要區別在於:SI可能會造成潛在的更新衝突。衝突發生是因為事務2在Quantity值為324的時候開始,當這個值被事務1更新後,行版本324被存儲到版本存儲區內。事務2會在事務的持續時間內繼續讀取該行數據。如果兩個更新操作都被允許成功執行的話,就會產生經典的更新丟失情形。事務1增加了200個數量,然後事務2會在初始值上增加300個數量並存儲。由第一個事務增加的那200個產品就會徹底丟失,SQL Server不會允許這樣的情況發生。
當事務2開始嘗試執行更新時,並不會立刻得到一個錯誤——僅僅是被阻塞。事務1在行上擁有一個排他鎖,因此事務2嘗試獲取排他鎖時會被阻塞。如果事務1回滾,那麼事務2就能夠完成更新。但事務1最終被提交了,SQL Server檢測到一個衝突並產生錯誤。
衝突只可能發生在SI模式下,因為SI隔離級別是基於事務而不是基於語句的。如果上述例子在一個採用RCSI的資料庫中執行,事務2執行的更新語句不會使用該數據的原來值。當試圖讀取當前的Quantity值時,它會被阻塞住,而接著事務1完成時,它就能讀取更新過的Quantity將其作為當前值並再增加300,沒有一個更新會丟失。
如果用戶選擇工作在SI模式下就需要註意可能發生的衝突,它們能夠被減少到最低限度,但是如同死鎖一樣,用戶不能保證不發生衝突。用戶必須寫程式來合理地處理衝突,並且不能想當然地認為更新已經成功了。如果衝突只是偶然發生,用戶可能需要將其作為使用SI模式的部分代價考慮在內,但如果衝突太過頻繁,就需要額外措施來避免衝突。
3 參考文獻
【01】http://blog.jobbole.com/104445/
4 版權
- 感謝您的閱讀,若有不足之處,歡迎指教,共同學習、共同進步。
- 博主網址:http://www.cnblogs.com/wangjiming/。
- 極少部分文章利用讀書、參考、引用、抄襲、複製和粘貼等多種方式整合而成的,大部分為原創。
- 如您喜歡,麻煩推薦一下;如您有新想法,歡迎提出,郵箱:[email protected]。
- 可以轉載該博客,但必須著名博客來源。