Sqlserver2000中的并發(fā)問題
當前位置:點晴教程→知識管理交流
→『 技術(shù)文檔交流 』
sqlserver2000中的并發(fā)問題一、并發(fā)問題的產(chǎn)生:
如果沒有鎖定且多個用戶同時訪問一個數(shù)據(jù)庫,則當他們的事務(wù)同時使用相同的數(shù)據(jù)時可能會發(fā)生問題。并發(fā)問題包括: 丟失或覆蓋更新。未確認的相關(guān)性(臟讀)。不一致的分析(非重復讀)?;孟褡x。 1、丟失更新:當兩個或多個事務(wù)選擇同一行,然后基于最初選定的值更新該行時,會發(fā)生丟失更新問題。每個事務(wù)都不知道其它事務(wù)的存在。最后的更新將重寫由其它事務(wù)所做的更新,這將導致數(shù)據(jù)丟失。 例如,兩個編輯人員制作了同一文檔的電子復本。每個編輯人員獨立地更改其復本,然后保存更改后的復本,這樣就覆蓋了原始文檔。最后保存其更改復本的編輯人員覆蓋了第一個編輯人員所做的更改。如果在第一個編輯人員完成之后第二個編輯人員才能進行更改,則可以避免該問題。 2、未確認的相關(guān)性(臟讀) 當?shù)诙€事務(wù)選擇其它事務(wù)正在更新的行時,會發(fā)生未確認的相關(guān)性問題。第二個事務(wù)正在讀取的數(shù)據(jù)還沒有確認并且可能由更新此行的事務(wù)所更改。 例如,一個編輯人員正在更改電子文檔。在更改過程中,另一個編輯人員復制了該文檔(該復本包含到目前為止所做的全部更改)并將其分發(fā)給預期的用戶。此后,第一個編輯人員認為目前所做的更改是錯誤的,于是刪除了所做的編輯并保存了文檔。分發(fā)給用戶的文檔包含不再存在的編輯內(nèi)容,并且這些編輯內(nèi)容應認為從未存在過。如果在第一個編輯人員確定最終更改前任何人都不能讀取更改的文檔,則可以避免該問題。 3、不一致的分析(非重復讀) 當?shù)诙€事務(wù)多次訪問同一行而且每次讀取不同的數(shù)據(jù)時,會發(fā)生不一致的分析問題。不一致的分析與未確認的相關(guān)性類似,因為其它事務(wù)也是正在更改第二個事務(wù)正在讀取的數(shù)據(jù)。然而,在不一致的分析中,第二個事務(wù)讀取的數(shù)據(jù)是由已進行了更改的事務(wù)提交的。而且,不一致的分析涉及多次(兩次或更多)讀取同一行,而且每次信息都由其它事務(wù)更改;因而該行被非重復讀取。 例如,一個編輯人員兩次讀取同一文檔,但在兩次讀取之間,作者重寫了該文檔。當編輯人員第二次讀取文檔時,文檔已更改。原始讀取不可重復。如果只有在作者全部完成編寫后編輯人員才可以讀取文檔,則可以避免該問題。 4、幻像讀 當對某行執(zhí)行插入或刪除操作,而該行屬于某個事務(wù)正在讀取的行的范圍時,會發(fā)生幻像讀問題。事務(wù)第一次讀的行范圍顯示出其中一行已不復存在于第二次讀或后續(xù)讀中,因為該行已被其它事務(wù)刪除。同樣,由于其它事務(wù)的插入操作,事務(wù)的第二次或后續(xù)讀顯示有一行已不存在于原始讀中。 例如,一個編輯人員更改作者提交的文檔,但當生產(chǎn)部門將其更改內(nèi)容合并到該文檔的主復本時,發(fā)現(xiàn)作者已將未編輯的新材料添加到該文檔中。如果在編輯人員和生產(chǎn)部門完成對原始文檔的處理之前,任何人都不能將新材料添加到文檔中,則可以避免該問題。 二、并發(fā)問題的解決方案: 當鎖定用作并發(fā)控制機制時,它可以解決并發(fā)問題。這使所有事務(wù)得以在彼此完全隔離的環(huán)境中運行,但是任何時候都可以有多個正在運行的事務(wù)。 可串行性是通過運行一組并發(fā)事務(wù)達到的數(shù)據(jù)庫狀態(tài),等同于這組事務(wù)按某種順序連續(xù)執(zhí)行時所達到的數(shù)據(jù)庫狀態(tài)。 sql-92 隔離級別 盡管可串行性對于事務(wù)確保數(shù)據(jù)庫中的數(shù)據(jù)在所有時間內(nèi)的正確性相當重要,然而許多事務(wù)并不總是要求完全的隔離。例如,多個作者工作于同一本書的不同章節(jié)。新章節(jié)可以在任意時候提交到項目中。但是,對于已經(jīng)編輯過的章節(jié),沒有編輯人員的批準,作者不能對此章節(jié)進行任何更改。這樣,盡管有未編輯的新章節(jié),但編輯人員仍可以確保在任意時間該書籍項目的正確性。編輯人員可以查看以前編輯的章節(jié)以及最近提交的章節(jié)。 事務(wù)準備接受不一致數(shù)據(jù)的級別稱為隔離級別。隔離級別是一個事務(wù)必須與其它事務(wù)進行隔離的程度。較低的隔離級別可以增加并發(fā),但代價是降低數(shù)據(jù)的正確性。相反,較高的隔離級別可以確保數(shù)據(jù)的正確性,但可能對并發(fā)產(chǎn)生負面影響。應用程序要求的隔離級別確定了 sql server 使用的鎖定行為。 sql-92 定義了下列四種隔離級別,sql server 支持所有這些隔離級別: 未提交讀(事務(wù)隔離的最低級別,僅可保證不讀取物理損壞的數(shù)據(jù))。提交讀(sql server 默認級別)??芍貜妥x。可串行讀(事務(wù)隔離的最高級別,事務(wù)之間完全隔離)。 如果事務(wù)在可串行讀隔離級別上運行,則可以保證任何并發(fā)重疊事務(wù)均是串行的。 下面四種隔離級別允許不同類型的行為。 隔離級別 臟讀 不可重復讀取 幻像 未提交讀 是 是 是 提交讀 否 是 是 可重復讀 否 否 是 可串行讀 否 否 否 事務(wù)必須運行于可重復讀或更高的隔離級別以防止丟失更新。當兩個事務(wù)檢索相同的行,然后基于原檢索的值對行進行更新時,會發(fā)生丟失更新。如果兩個事務(wù)使用一個 update 語句更新行,并且不基于以前檢索的值進行更新,則在默認的提交讀隔離級別不會發(fā)生丟失更新。 三、問題解決的實現(xiàn): 1、 默認解決方案:set transaction isolation level 控制由連接發(fā)出的所有 microsoft® sql server™ select 語句的默認事務(wù)鎖定行為。 語法 set transaction isolation level { read committed | read uncommitted | repeatable read | serializable } 參數(shù) read committed 指定在讀取數(shù)據(jù)時控制共享鎖以避免臟讀,但數(shù)據(jù)可在事務(wù)結(jié)束前更改,從而產(chǎn)生不可重復讀取或幻像數(shù)據(jù)。該選項是 sql server 的默認值。 read uncommitted 執(zhí)行臟讀或 0 級隔離鎖定,這表示不發(fā)出共享鎖,也不接受排它鎖。當設(shè)置該選項時,可以對數(shù)據(jù)執(zhí)行未提交讀或臟讀;在事務(wù)結(jié)束前可以更改數(shù)據(jù)內(nèi)的數(shù)值,行也可以出現(xiàn)在數(shù)據(jù)集中或從數(shù)據(jù)集消失。該選項的作用與在事務(wù)內(nèi)所有語句中的所有表上設(shè)置 nolock 相同。這是四個隔離級別中限制最小的級別。 repeatable read 鎖定查詢中使用的所有數(shù)據(jù)以防止其他用戶更新數(shù)據(jù),但是其他用戶可以將新的幻像行插入數(shù)據(jù)集,且幻像行包括在當前事務(wù)的后續(xù)讀取中。因為并發(fā)低于默認隔離級別,所以應只在必要時才使用該選項。 serializable 在數(shù)據(jù)集上放置一個范圍鎖,以防止其他用戶在事務(wù)完成之前更新數(shù)據(jù)集或?qū)⑿胁迦霐?shù)據(jù)集內(nèi)。這是四個隔離級別中限制最大的級別。因為并發(fā)級別較低,所以應只在必要時才使用該選項。該選項的作用與在事務(wù)內(nèi)所有 select 語句中的所有表上設(shè)置 holdlock 相同。 注釋 一次只能設(shè)置這些選項中的一個,而且設(shè)置的選項將一直對那個連接保持有效,直到顯式更改該選項為止。這是默認行為,除非在語句的 from 子句中在表級上指定優(yōu)化選項。 set transaction isolation level 的設(shè)置是在執(zhí)行或運行時設(shè)置,而不是在分析時設(shè)置。 示例 下例為會話設(shè)置 transaction isolation level。對于每個后續(xù) transact-sql 語句,sql server 將所有共享鎖一直控制到事務(wù)結(jié)束為止。 set transaction isolation level repeatable read go begin transaction select * from publishers select * from authors ... commit transaction 2、自定義事務(wù)隔離級別 默認情況下,microsoft® sql server™ 2000 在 read committed 的一個隔離級別上操作。但是,應用程序可能必須運行于不同的隔離級別。若要在應用程序中使用更嚴格或較寬松的隔離級別,可以通過使用 set transaction isolation level 語句設(shè)置會話的隔離級別,來自定義整個會話的鎖定。 指定隔離級別后,sql server 會話中所有 select 語句的鎖定行為都運行于該隔離級別上,并一直保持有效直到會話終止或者將隔離級別設(shè)置為另一個級別。例如,若要設(shè)置事務(wù)隔離級別為可串行讀,以確保并發(fā)事務(wù)不能在 authors 表中插入幻像行,請執(zhí)行: use pubs go set transaction isolation level serializable go begin transaction select au_lname from authors 說明 如果必要,可以通過指定表級鎖定提示來替代單個 select 語句的隔離級別。指定表級鎖定提示不會影響會話中的其它語句。建議僅在絕對必要時才使用表級鎖定提示更改默認的鎖定行為。 若要確定當前設(shè)置的事務(wù)隔離級別,請使用 dbcc useroptions 語句,例如: use pubs go set transaction isolation level repeatable read go dbcc useroptions go set option value textsize 4096 language us_english dateformat mdy datefirst 7 isolation level repeatable read (5 rows affected) dbcc execution completed. if dbcc printed error messages, see your system administrator. 3、調(diào)整事務(wù)隔離級別 隔離屬性是 acid 的四個屬性之一,邏輯工作單元必須具備這四個屬性才能稱為事務(wù)。該屬性能夠使事務(wù)免受其它并發(fā)事務(wù)所執(zhí)行的更新的影響。每個事務(wù)的隔離級別實際上都是可以自定義的。 microsoft® sql server™ 支持 sql-92 中定義的事務(wù)隔離級別。設(shè)置事務(wù)隔離級別雖然使程序員承擔了某些完整性問題所帶來的風險,但可以換取對數(shù)據(jù)更大的并發(fā)訪問權(quán)。與以前的隔離級別相比,每個隔離級別都提供了更大的隔離性,但這是通過在更長的時間內(nèi)占用更多限制鎖換來的。事務(wù)隔離級別有: read uncommittedread committedrepeatable readserializable 可以使用 transact-sql 或通過數(shù)據(jù)庫 api 來設(shè)置事務(wù)隔離級別: transact-sql transact-sql 腳本和 db-library 應用程序使用 set transaction isolation level 語句。 ado ado 應用程序?qū)?connection 對象的 isolationlevel 屬性設(shè)置為 adxactreaduncommitted、adxactreadcommitted、adxactrepeatableread 或 adxactreadserializable。 ole db ole db 應用程序調(diào)用 itransactionlocal::starttransaction,其中 isolevel 設(shè)置為 isolationlevel_readuncommitted、isolationlevel_readcommitted、isolationlevel_repeatableread 或 isolationlevel_serializable。 odbc odbc 應用程序調(diào)用 sqlsetconnectattr,其中 attribute 設(shè)置為 sql_attr_txn_isolation,valueptr 設(shè)置為 sql_txn_read_uncommitted、sql_txn_read_committed、sql_txn_repeatable_read 或 sql_txn_serializable。 該文章在 2011/3/3 16:34:49 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |