SET TRANSACTION ISOLATION LEVEL (Transact-SQL)

SET TRANSACTION ISOLATION LEVEL (Transact-SQL) 控制到 SQL Server 的連接發出的 Transact-SQL 語句的鎖定行爲和行版本控制行爲。 Transact-SQL 語法約定 語法 SET TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SNAPSHOT | SERIALIZABLE } [ ; ] 參數 READ UNCOMMITTED 指定語句可以讀取已由其他事務修改但尚未提交的行。 在 READ UNCOMMITTED 級別運行的事務,不會發出共享鎖來防止其他事務修改當前事務讀取的數據。READ UNCOMMITTED 事務也不會被排他鎖阻塞,排他鎖會禁止當前事務讀取其他事務已修改但尚未提交的行。設置此選項之後,可以讀取未提交的修改,這種讀取稱爲髒讀。在事務結束之前,可以更改數據中的值,行也可以出現在數據集中或從數據集中消失。該選項的作用與在事務內所有 SELECT 語句中的所有表上設置 NOLOCK 相同。這是隔離級別中限制最少的級別。 在 SQL Server 中,您還可以使用下列任意一種方法,在保護事務不髒讀未提交的數據修改的同時儘量減少鎖定爭用: READ COMMITTED 隔離級別,並將 READ_COMMITTED_SNAPSHOT 數據庫選項設置爲 ON。 SNAPSHOT 隔離級別。 READ COMMITTED 指定語句不能讀取已由其他事務修改但尚未提交的數據。這樣可以避免髒讀。其他事務可以在當前事務的各個語句之間更改數據,從而產生不可重複讀取和幻像數據。該選項是 SQL Server 的默認設置。 READ COMMITTED 的行爲取決於 READ_COMMITTED_SNAPSHOT 數據庫選項的設置: 如果將 READ_COMMITTED_SNAPSHOT 設置爲 OFF(默認設置),則數據庫引擎會使用共享鎖防止其他事務在當前事務執行讀取操作期間修改行。共享鎖還會阻止語句在其他事務完成之前讀取由這些事務修改的行。共享鎖類型確定它將於何時釋放。行鎖在處理下一行之前釋放。頁鎖在讀取下一頁時釋放,表鎖在語句完成時釋放。 如果將 READ_COMMITTED_SNAPSHOT 設置爲 ON,則數據庫引擎會使用行版本控制爲每個語句提供一個在事務上一致的數據快照,因爲該數據在語句開始時就存在。不使用鎖來防止其他事務更新數據。 當 READ_COMMITTED_SNAPSHOT 數據庫選項設置爲 ON 時,您可以使用 READCOMMITTEDLOCK 表提示爲 READ COMMITTED 隔離級別上運行的事務中的各語句請求共享鎖,而不是行版本控制。 注意: 設置 READ_COMMITTED_SNAPSHOT 選項時,數據庫中僅允許存在執行 ALTER DATABASE 命令的連接。在 ALTER DATABASE 完成之前,數據庫中不允許有其他打開的連接。數據庫不必處於單用戶模式。 REPEATABLE READ 指定語句不能讀取已由其他事務修改但尚未提交的行,並且指定,其他任何事務都不能在當前事務完成之前修改由當前事務讀取的數據。 對事務中的每個語句所讀取的全部數據都設置了共享鎖,並且該共享鎖一直保持到事務完成爲止。這樣可以防止其他事務修改當前事務讀取的任何行。其他事務可以插入與當前事務所發出語句的搜索條件相匹配的新行。如果當前事務隨後重試執行該語句,它會檢索新行,從而產生幻讀。由於共享鎖一直保持到事務結束,而不是在每個語句結束時釋放,所以併發級別低於默認的 READ COMMITTED 隔離級別。此選項只在必要時使用。 SNAPSHOT 指定事務中任何語句讀取的數據都將是在事務開始時便存在的數據的事務上一致的版本。事務只能識別在其開始之前提交的數據修改。在當前事務中執行的語句將看不到在當前事務開始以後由其他事務所做的數據修改。其效果就好像事務中的語句獲得了已提交數據的快照,因爲該數據在事務開始時就存在。 除非正在恢復數據庫,否則 SNAPSHOT 事務不會在讀取數據時請求鎖。讀取數據的 SNAPSHOT 事務不會阻止其他事務寫入數據。寫入數據的事務也不會阻止 SNAPSHOT 事務讀取數據。 在數據庫恢復的回滾階段,如果嘗試讀取由其他正在回滾的事務鎖定的數據,則 SNAPSHOT 事務將請求一個鎖。在事務完成回滾之前,SNAPSHOT 事務會一直被阻塞。當事務取得授權之後,便會立即釋放鎖。 必須將 ALLOW_SNAPSHOT_ISOLATION 數據庫選項設置爲 ON,才能開始一個使用 SNAPSHOT 隔離級別的事務。如果使用 SNAPSHOT 隔離級別的事務訪問多個數據庫中的數據,則必須在每個數據庫中將 ALLOW_SNAPSHOT_ISOLATION 都設置爲 ON。 不能將通過其他隔離級別開始的事務設置爲 SNAPSHOT 隔離級別,否則將導致事務中止。如果一個事務在 SNAPSHOT 隔離級別開始,則可以將它更改爲另一個隔離級別,然後再返回 SNAPSHOT。事務在第一次訪問數據時啓動。 在 SNAPSHOT 隔離級別下運行的事務可以查看由該事務所做的更改。例如,如果事務對錶執行 UPDATE,然後對同一個表發出 SELECT 語句,則修改後的數據將包含在結果集中。 SERIALIZABLE 請指定下列內容: 語句不能讀取已由其他事務修改但尚未提交的數據。 任何其他事務都不能在當前事務完成之前修改由當前事務讀取的數據。 在當前事務完成之前,其他事務不能使用當前事務中任何語句讀取的鍵值插入新行。 範圍鎖處於與事務中執行的每個語句的搜索條件相匹配的鍵值範圍之內。這樣可以阻止其他事務更新或插入任何行,從而限定當前事務所執行的任何語句。這意味着如果再次執行事務中的任何語句,則這些語句便會讀取同一組行。在事務完成之前將一直保持範圍鎖。這是限制最多的隔離級別,因爲它鎖定了鍵的整個範圍,並在事務完成之前一直保持範圍鎖。因爲併發級別較低,所以應只在必要時才使用該選項。該選項的作用與在事務內所有 SELECT 語句中的所有表上設置 HOLDLOCK 相同。 註釋 一次只能設置一個隔離級別選項,而且設置的選項將一直對那個連接始終有效,直到顯式更改該選項爲止。事務中執行的所有讀取操作都會在指定的隔離級別的規則下運行,除非語句的 FROM 子句中的表提示爲表指定了其他鎖定行爲或版本控制行爲。 事務隔離級別定義了可爲讀取操作獲取的鎖類型。針對 READ COMMITTED 或 REPEATABLE READ 獲取的共享鎖通常爲行鎖,儘管當讀取引用了頁或表中大量的行時,行鎖可以升級爲頁鎖或表鎖。如果某行在被讀取之後由事務進行了修改,則該事務會獲取一個用於保護該行的排他鎖,並且該排他鎖在事務完成之前將一直保持。例如,如果 REPEATABLE READ 事務具有用於某行的共享鎖,並且該事務隨後修改了該行,則共享行鎖便會轉換爲排他行鎖。 在事務進行期間,可以隨時將事務從一個隔離級別切換到另一個隔離級別,但有一種情況例外。即在從任一隔離級別更改到 SNAPSHOT 隔離時,不能進行上述操作。否則會導致事務失敗並回滾。但是,可以將在 SNAPSHOT 隔離中啓動的事務更改爲任何其他隔離級別。 將事務從一個隔離級別更改爲另一個隔離級別之後,便會根據新級別的規則對更改後讀取的資源執行保護。在更改前讀取的資源將繼續按照以前級別的規則受到保護。例如,如果某個事務從 READ COMMITTED 更改爲 SERIALIZABLE,則在該事務結束前,更改後所獲取的共享鎖將一直處於保留狀態。 如果在存儲過程或觸發器中發出 SET TRANSACTION ISOLATION LEVEL,則當對象返回控制時,隔離級別會重設爲在調用對象時有效的級別。例如,如果在批處理中設置 REPEATABLE READ,並且該批處理調用一個將隔離級別設置爲 SERIALIZABLE 的存儲過程,則當該存儲過程將控制返回給該批處理時,隔離級別就會恢復爲 REPEATABLE READ。 注意: 用戶定義的函數和公共語言運行時 (CLR) 用戶定義的類型無法執行 SET TRANSACTION ISOLATION LEVEL。但是,可通過使用表提示來重寫隔離級別。有關詳細信息,請參閱表提示 (Transact-SQL)。 當您使用 sp_bindsession 綁定兩個會話時,每個會話都會保留它自身的隔離級別設置。使用 SET TRANSACTION ISOLATION LEVEL 更改某個會話的隔離級別設置時,不會影響與該會話綁定的其他任何會話的設置。 SET TRANSACTION ISOLATION LEVEL 會在執行或運行時生效,而不是在分析時生效。 針對堆的優化大容量負載操作阻塞了運行在以下隔離級別下面的查詢: SNAPSHOT READ UNCOMMITTED 使用行版本控制的 READ COMMITTED 相反,運行在這些隔離級別下面的查詢阻塞了針對堆的優化大容量負載操作。有關大容量加載操作的詳細信息,請參閱關於大容量導入和大容量導出操作和優化大容量導入性能。 示例 以下示例爲會話設置了 TRANSACTION ISOLATION LEVEL。對於每個後續 Transact-SQL 語句,SQL Server 將所有共享鎖一直保持到事務結束爲止。 複製代碼 USE AdventureWorks; GO SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; GO BEGIN TRANSACTION; GO SELECT * FROM HumanResources.EmployeePayHistory; GO SELECT * FROM HumanResources.Department; GO COMMIT TRANSACTION; GO
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章