MSSQL事務隔離級別詳解(SET TRANSACTION ISOLATION LEVEL)


控制到 Transact-SQL 的連接發出的 SQL Server 語句的鎖定行為和行版本控制行為。

主題鏈接圖標 TRANSACT-SQL 語法約定

語法

 
-- Syntax for SQL Server and Azure SQL Database

SET TRANSACTION ISOLATION LEVEL
    { READ UNCOMMITTED
    | READ COMMITTED
    | REPEATABLE READ
    | SNAPSHOT
    | SERIALIZABLE
    }
 
-- Syntax for Azure SQL Data Warehouse and Parallel Data Warehouse

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

參數

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,則 數據庫引擎會使用行版本控制為每個語句提供一個在事務上一致的數據快照,因為該數據在語句開始時就存在。 不使用鎖來防止其他事務更新數據。

    快照隔離支持 FILESTREAM 數據。 在快照隔離模式下,事務中任何語句讀取的 FILESTREAM 數據都將是在事務開始時便存在的數據的事務性一致版本。

    當 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 語句,則修改后的數據將包含在結果集中。

備注

在快照隔離模式下,事務中任何語句讀取的 FILESTREAM 數據都將是在事務開始(而非語句開始)時便存在的數據的事務性一致版本。

SERIALIZABLE
請指定下列內容:

  • 語句不能讀取已由其他事務修改但尚未提交的數據。

  • 任何其他事務都不能在當前事務完成之前修改由當前事務讀取的數據。

  • 在當前事務完成之前,其他事務不能使用當前事務中任何語句讀取的鍵值插入新行。

    范圍鎖處於與事務中執行的每個語句的搜索條件相匹配的鍵值范圍之內。 這樣可以阻止其他事務更新或插入任何行,從而限定當前事務所執行的任何語句。 這意味着如果再次執行事務中的任何語句,則這些語句便會讀取同一組行。 在事務完成之前將一直保持范圍鎖。 這是限制最多的隔離級別,因為它鎖定了鍵的整個范圍,並在事務完成之前一直保持范圍鎖。 因為並發級別較低,所以應只在必要時才使用該選項。 該選項的作用與在事務內所有 SELECT 語句中的所有表上設置 HOLDLOCK 相同。

Remarks

一次只能設置一個隔離級別選項,而且設置的選項將一直對那個連接始終有效,直到顯式更改該選項為止。 事務中執行的所有讀取操作都會在指定的隔離級別的規則下運行,除非語句的 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

    相反,運行在這些隔離級別下面的查詢阻塞了針對堆的優化大容量負載操作。 有關大容量加載操作的詳細信息,請參閱批量導入和導出數據 (SQL Server)

    已啟用 FILESTREAM 的數據庫支持下列事務隔離級別。

隔離級別 Transact SQL 訪問 文件系統訪問
未提交讀 SQL Server 2017 不支持
已提交讀 SQL Server 2017 SQL Server 2017
可重復讀 SQL Server 2017 不支持
可序列化 SQL Server 2017 不支持
讀提交的快照 SQL Server 2017 SQL Server 2017
快照 SQL Server 2017 SQL Server 2017

示例

以下示例為會話設置了 TRANSACTION ISOLATION LEVEL對於每個后續 Transact-SQL 語句, SQL Server 將所有共享鎖一直保持到事務結束為止。

 
USE AdventureWorks2012;  
GO  
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;  
GO  
BEGIN TRANSACTION;  
GO  
SELECT *   
    FROM HumanResources.EmployeePayHistory;  
GO  
SELECT *   
    FROM HumanResources.Department;  
GO  
COMMIT TRANSACTION;  
GO  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM