語法
SET TRANSACTION ISOLATION LEVEL ????{ READ UNCOMMITTED ????| READ COMMITTED ????| REPEATABLE READ ????| SNAPSHOT ????| SERIALIZABLE ????} [ ; ] |
備注
一次只能設(shè)置一個隔離級別選項,而且設(shè)置的選項將一直對那個連接始終有效,直到顯式更改該選項為止。事務(wù)中執(zhí)行的所有讀取操作都會在指定的隔離級別的規(guī)則下運行,除非語句的 FROM 子句中的表提示為表指定了其他鎖定行為或版本控制行為。
事務(wù)隔離級別定義了可為讀取操作獲取的鎖類型。針對 READ COMMITTED 或 REPEATABLE READ 獲取的共享鎖通常為行鎖,盡管當(dāng)讀取引用了頁或表中大量的行時,行鎖可以升級為頁鎖或表鎖。如果某行在被讀取之后由事務(wù)進行了修改,則該事務(wù)會獲取一個用于保護該行的排他鎖,并且該排他鎖在事務(wù)完成之前將一直保持。例如,如果 REPEATABLE READ 事務(wù)具有用于某行的共享鎖,并且該事務(wù)隨后修改了該行,則共享行鎖便會轉(zhuǎn)換為排他行鎖。
當(dāng)事務(wù)進行時,您可以隨時將事務(wù)從一個隔離級別更改為另一個隔離級別。將事務(wù)從一個隔離級別更改為另一個隔離級別之后,便會根據(jù)新級別的規(guī)則對更改后讀取的資源執(zhí)行保護。更改前讀取的資源將繼續(xù)根據(jù)先前級別的規(guī)則進行保護,例如,一個事務(wù)由 REPEATABLE READ 更改為 SERIALIZABLE。由更改前發(fā)出的 SELECT 語句讀取的行將繼續(xù)受到行級、頁級或表級共享鎖的保護。這些鎖會繼續(xù)保持,直至事務(wù)結(jié)束。由 SELECT 語句在更改后讀取的行將受到范圍鎖的保護。
該表顯示事務(wù)從一個隔離級別更改為另一個隔離級別時的鎖定行為。
?
更改前的隔離級別 更改后的隔離級別
READ UNCOMMITTED |
READ UNCOMITTED: 未更改。 READ COMMITTED: 該行為取決于 READ_COMMITTED_SNAPSHOT 數(shù)據(jù)庫選項的設(shè)置: 如果為 OFF,事務(wù)將獲取共享鎖,并在讀取期間保留鎖。 如果為 ON,事務(wù)會使用行版本控制。 SNAPSHOT: 事務(wù)必須已作為 SNAPSHOT 啟動。事務(wù)將會失敗,并將回滾所有更改。 REPEATABLE READ: 現(xiàn)在該事務(wù)將獲取共享鎖,并在事務(wù)期間保留鎖。 SERIALIZABLE: 現(xiàn)在該事務(wù)將獲取范圍鎖,并在事務(wù)期間保留鎖。 |
READ COMMITTED |
READ UNCOMITTED: 事務(wù)不再獲取用于讀取操作的鎖。 READ COMMITTED: 未更改。 SNAPSHOT: 事務(wù)必須已作為 SNAPSHOT 啟動。事務(wù)將會失敗,并將回滾所有更改。 REPEATABLE READ: 現(xiàn)在該事務(wù)將獲取共享鎖,并在事務(wù)期間保留鎖。 SERIALIZABLE: 現(xiàn)在該事務(wù)將獲取范圍鎖,并在事務(wù)期間保留鎖。 |
SNAPSHOT |
READ UNCOMITTED: 事務(wù)不再使用行版本控制,并且不再獲取用于讀取操作的鎖。 READ COMMITTED: 該行為取決于 READ_COMMITTED_SNAPSHOT 數(shù)據(jù)庫選項的設(shè)置: 如果為 OFF,事務(wù)將獲取共享鎖,并在讀取期間保留鎖。 如果為 ON,事務(wù)會使用行版本控制。 SNAPSHOT: 未更改。 REPEATABLE READ: 該事務(wù)不再使用行版本控制。現(xiàn)在它獲取了共享鎖,并在事務(wù)執(zhí)行期間一直保持該鎖。 SERIALIZABLE: 該事務(wù)不再使用行版本控制。現(xiàn)在它獲取了范圍鎖,并在事務(wù)執(zhí)行期間一直保持該鎖。 |
REPEATABLE READ |
READ UNCOMITTED: 該事務(wù)在讀取操作時不再獲取鎖。在 REPEATABLE READ 下獲取的共享鎖保留到事務(wù)結(jié)束。 READ COMMITTED: 該行為取決于 READ_COMMITTED_SNAPSHOT 數(shù)據(jù)庫選項的設(shè)置: 如果為 OFF,事務(wù)將獲取共享鎖,并在讀取期間保留這些新鎖。 如果為 ON,事務(wù)會使用行版本控制。 在 REPEATABLE READ 下獲取的共享鎖保留到事務(wù)結(jié)束。 SNAPSHOT: 事務(wù)必須已作為 SNAPSHOT 啟動。事務(wù)將會失敗,并將回滾所有更改。 REPEATABLE READ: 未更改。 SERIALIZABLE: 現(xiàn)在該事務(wù)將獲取范圍鎖,并在事務(wù)期間保留鎖。在 REPEATABLE READ 下獲取的共享鎖保留到事務(wù)結(jié)束。 |
SERIALIZABLE |
READ UNCOMITTED: 該事務(wù)在讀取操作時不再獲取鎖。在 SERIALIZABLE 下獲取的范圍鎖保留到事務(wù)結(jié)束。 READ COMMITTED: 該行為取決于 READ_COMMITTED_SNAPSHOT 數(shù)據(jù)庫選項的設(shè)置: 如果為 OFF,事務(wù)將獲取共享鎖,并在讀取期間保留這些新鎖。 如果為 ON,事務(wù)會使用行版本控制。 在 SERIALIZABLE 級別下獲取了范圍鎖,并且該鎖一直保持到事務(wù)結(jié)束。 SNAPSHOT: 事務(wù)必須已作為 SNAPSHOT 啟動。事務(wù)將會失敗,并將回滾所有更改。 REPEATABLE READ: 現(xiàn)在,事務(wù)獲取了共享鎖,并在事務(wù)執(zhí)行期間一直保持該鎖。在 SERIALIZABLE 下獲取的范圍鎖保留到事務(wù)結(jié)束。 SERIALIZABLE: 未更改。 |
如果在存儲過程、觸發(fā)器、用戶定義函數(shù)或用戶定義類型中發(fā)出 SET TRANSACTION ISOLATION LEVEL,則當(dāng)對象返回控制時,隔離級別會重設(shè)為在調(diào)用對象時有效的級別。例如,如果在批處理中設(shè)置 REPEATABLE READ,并且該批處理調(diào)用一個將隔離級別設(shè)置為 SERIALIZABLE 的存儲過程,則當(dāng)該存儲過程將控制返回給該批處理時,隔離級別就會恢復(fù)為 REPEATABLE READ。
當(dāng)您使用 sp_bindsession 綁定兩個會話時,每個會話都會保留它自身的隔離級別設(shè)置。使用 SET TRANSACTION ISOLATION LEVEL 更改某個會話的隔離級別設(shè)置時,不會影響與該會話綁定的其他任何會話的設(shè)置。
SET TRANSACTION ISOLATION LEVEL 會在執(zhí)行或運行時生效,而不是在分析時生效。
對表執(zhí)行的優(yōu)化大容量導(dǎo)入操作會阻塞在下列隔離級別下運行的查詢:
SNAPSHOT
READ UNCOMMITTED
使用行版本控制的 READ COMMITTED
反之,在這些隔離級別下運行的查詢也會阻塞優(yōu)化大容量導(dǎo)入操作。
參數(shù)
指定語句可以讀取已由其他事務(wù)修改但尚未提交的行。
在 READ UNCOMMITTED 級別運行的事務(wù),不會發(fā)出共享鎖來防止其他事務(wù)修改當(dāng)前事務(wù)讀取的數(shù)據(jù)。READ UNCOMMITTED 事務(wù)也不會被排他鎖阻塞,排他鎖會禁止當(dāng)前事務(wù)讀取其他事務(wù)已修改但尚未提交的行。設(shè)置此選項之后,可以讀取未提交的修改,這種讀取稱為臟讀。在事務(wù)結(jié)束之前,可以更改數(shù)據(jù)中的值,行也可以出現(xiàn)在數(shù)據(jù)集中或從數(shù)據(jù)集中消失。該選項的作用與在事務(wù)內(nèi)所有 SELECT 語句中的所有表上設(shè)置 NOLOCK 相同。這是隔離級別中限制最少的級別。
在 SQL Server 2005 中,您還可以使用下列任意一種方法,在保護事務(wù)不臟讀未提交的數(shù)據(jù)修改的同時盡量減少鎖定爭用:
READ COMMITTED 隔離級別,并將 READ_COMMITTED_SNAPSHOT 數(shù)據(jù)庫選項設(shè)置為 ON。
SNAPSHOT 隔離級別。
指定語句不能讀取已由其他事務(wù)修改但尚未提交的數(shù)據(jù)。這樣可以避免臟讀。其他事務(wù)可以在當(dāng)前事務(wù)的各個語句之間更改數(shù)據(jù),從而產(chǎn)生不可重復(fù)讀取和幻像數(shù)據(jù)。該選項是 SQL Server 的默認設(shè)置。
READ COMMITTED 的行為取決于 READ_COMMITTED_SNAPSHOT 數(shù)據(jù)庫選項的設(shè)置:
如果將 READ_COMMITTED_SNAPSHOT 設(shè)置為 OFF(默認設(shè)置),則數(shù)據(jù)庫引擎?會使用共享鎖防止其他事務(wù)在當(dāng)前事務(wù)執(zhí)行讀取操作期間修改行。共享鎖還會阻止語句在其他事務(wù)完成之前讀取由這些事務(wù)修改的行。語句完成后便會釋放共享鎖。
如果將 READ_COMMITTED_SNAPSHOT 設(shè)置為 ON,則數(shù)據(jù)庫引擎?會使用行版本控制為每個語句提供一個在事務(wù)上一致的數(shù)據(jù)快照,因為該數(shù)據(jù)在語句開始時就存在。不使用鎖來防止其他事務(wù)更新數(shù)據(jù)。
當(dāng) READ_COMMITTED_SNAPSHOT 數(shù)據(jù)庫選項設(shè)置為 ON 時,您可以使用 READCOMMITTEDLOCK 表提示為 READ_COMMITTED 隔離級別上運行的事務(wù)中的各語句請求共享鎖,而不是行版本控制。
指定語句不能讀取已由其他事務(wù)修改但尚未提交的行,并且指定,其他任何事務(wù)都不能在當(dāng)前事務(wù)完成之前修改由當(dāng)前事務(wù)讀取的數(shù)據(jù)。
對事務(wù)中的每個語句所讀取的全部數(shù)據(jù)都設(shè)置了共享鎖,并且該共享鎖一直保持到事務(wù)完成為止。這樣可以防止其他事務(wù)修改當(dāng)前事務(wù)讀取的任何行。其他事務(wù)可以插入與當(dāng)前事務(wù)所發(fā)出語句的搜索條件相匹配的新行。如果當(dāng)前事務(wù)隨后重試執(zhí)行該語句,它會檢索新行,從而產(chǎn)生幻讀。由于共享鎖一直保持到事務(wù)結(jié)束,而不是在每個語句結(jié)束時釋放,所以并發(fā)級別低于默認的 READ COMMITTED 隔離級別。此選項只在必要時使用。
指定事務(wù)中任何語句讀取的數(shù)據(jù)都將是在事務(wù)開始時便存在的數(shù)據(jù)的事務(wù)上一致的版本。事務(wù)只能識別在其開始之前提交的數(shù)據(jù)修改。在當(dāng)前事務(wù)中執(zhí)行的語句將看不到在當(dāng)前事務(wù)開始以后由其他事務(wù)所做的數(shù)據(jù)修改。其效果就好像事務(wù)中的語句獲得了已提交數(shù)據(jù)的快照,因為該數(shù)據(jù)在事務(wù)開始時就存在。
除非正在恢復(fù)數(shù)據(jù)庫,否則 SNAPSHOT 事務(wù)不會在讀取數(shù)據(jù)時請求鎖。讀取數(shù)據(jù)的 SNAPSHOT 事務(wù)不會阻止其他事務(wù)寫入數(shù)據(jù)。寫入數(shù)據(jù)的事務(wù)也不會阻止 SNAPSHOT 事務(wù)讀取數(shù)據(jù)。
在數(shù)據(jù)庫恢復(fù)的回滾階段,如果嘗試讀取由其他正在回滾的事務(wù)鎖定的數(shù)據(jù),則 SNAPSHOT 事務(wù)將請求一個鎖。在事務(wù)完成回滾之前,SNAPSHOT 事務(wù)會一直被阻塞。當(dāng)事務(wù)取得授權(quán)之后,便會立即釋放鎖。
必須將 ALLOW_SNAPSHOT_ISOLATION 數(shù)據(jù)庫選項設(shè)置為 ON,才能開始一個使用 SNAPSHOT 隔離級別的事務(wù)。如果使用 SNAPSHOT 隔離級別的事務(wù)訪問多個數(shù)據(jù)庫中的數(shù)據(jù),則必須在每個數(shù)據(jù)庫中將 ALLOW_SNAPSHOT_ISOLATION 都設(shè)置為 ON。
不能將通過其他隔離級別開始的事務(wù)設(shè)置為 SNAPSHOT 隔離級別,否則將導(dǎo)致事務(wù)中止。如果一個事務(wù)在 SNAPSHOT 隔離級別開始,則可以將它更改為另一個隔離級別,然后再返回 SNAPSHOT。一個事務(wù)從執(zhí)行 BEGIN TRANSACTION 語句開始。
在 SNAPSHOT 隔離級別下運行的事務(wù)可以查看由該事務(wù)所做的更改。例如,如果事務(wù)對表執(zhí)行 UPDATE,然后對同一個表發(fā)出 SELECT 語句,則修改后的數(shù)據(jù)將包含在結(jié)果集中。
指定:
語句不能讀取已由其他事務(wù)修改但尚未提交的數(shù)據(jù)。
任何其他事務(wù)都不能在當(dāng)前事務(wù)完成之前修改由當(dāng)前事務(wù)讀取的數(shù)據(jù)。
在當(dāng)前事務(wù)完成之前,其他事務(wù)不能使用當(dāng)前事務(wù)中任何語句讀取的鍵值插入新行。
范圍鎖處于與事務(wù)中執(zhí)行的每個語句的搜索條件相匹配的鍵值范圍之內(nèi)。這樣可以阻止其他事務(wù)更新或插入任何行,從而限定當(dāng)前事務(wù)所執(zhí)行的任何語句。這意味著如果再次執(zhí)行事務(wù)中的任何語句,則這些語句便會讀取同一組行。在事務(wù)完成之前將一直保持范圍鎖。這是限制最多的隔離級別,因為它鎖定了鍵的整個范圍,并在事務(wù)完成之前一直保持范圍鎖。因為并發(fā)級別較低,所以應(yīng)只在必要時才使用該選項。該選項的作用與在事務(wù)內(nèi)所有 SELECT 語句中的所有表上設(shè)置 HOLDLOCK 相同。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
