SQL Server 事務隔離級別

来源:https://www.cnblogs.com/leohahah/archive/2018/02/24/8464575.html
-Advertisement-
Play Games

一、事務隔離級別控制著事務的如下表現: 在該行上的排他鎖被釋放之前阻塞其他事務。 檢索在啟動語句或事務時存在的行的已提交版本。 讀取未提交的數據修改。 在該行上的排他鎖被釋放之前阻塞其他事務。 檢索在啟動語句或事務時存在的行的已提交版本。 讀取未提交的數據修改。 以上說明事務隔離級別主要針對讀操作來 ...


一、事務隔離級別控制著事務的如下表現:

  1. 讀取數據時是否占用鎖以及所請求的鎖類型。
  2. 占用讀取鎖的時間。
  3. 引用其他事務修改的行的讀操作是否:
    • 在該行上的排他鎖被釋放之前阻塞其他事務。
    • 檢索在啟動語句或事務時存在的行的已提交版本。
    • 讀取未提交的數據修改。

以上說明事務隔離級別主要針對讀操作來說的。

二、臟讀、不可重覆讀、幻讀的區別:

提到事物隔離級別就不能不提這3個概念,可以說事務隔離級別就是為了避免這3種情況出現的。

臟讀:讀到了其他事務已修改但未提交的數據

不可重覆讀:同一事務中兩次查詢讀到的數據不同

幻讀:同一事務中兩次查詢讀到的記錄數不同

可能有人對幻讀和不可重覆讀的定義不太理解,兩者最大的區別實質上在於加鎖的不同,後邊會有講解。

三、ANSI/ISO標准定義了下列事務隔離級別,SQL Server資料庫引擎支持全部這4種隔離級別:

因此四種隔離級別與臟讀、幻讀、不可重覆讀的對應情況如下:

需要特別提醒的是:雖然Mysql、Oracle所支持的事務隔離級別也基本遵循ANSI標準,但卻有很大區別:

  • Oracle只支持已提交讀和序列化讀。
  • Mysql預設的的可重覆讀隔離級別通過範圍鎖實現了避免幻讀。

四、除以上4種隔離級別外SQL Server還支持使用行版本控制的其他兩個事務隔離級別:

  • 一個是預設的read committed隔離級別下的snapshot實現,嚴格來說並不算一個事務隔離級別,只是read committed的一個特殊形態。

  • 一個是全新的事務隔離級別----快照隔離級別。

兩者的開啟方式為:

1、如果要開啟SNAPSHOT事務隔離級別,需要預先設置ALLOW_SNAPSHOT_ISOLATION為ON,且目前只能修改會話級別的事務隔離級別。

ALTER DATABASE [dbname] SET ALLOW_SNAPSHOT_ISOLATION ON; --需要單用戶模式下修改,因為要加庫級別的獨占鎖。
 然後執行如下語句修改事務隔離級別:(修改後只在會話級別生效,無法修改全局級別的事務隔離級別)
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SNAPSHOT
| SERIALIZABLE
}

2、使用READ_COMMITTED_SNAPSHOT,則直接執行下列ALTER語句修改,是在預設的READ COMMITTED隔離級別下修改的,此隔離級別修改後永久生效,使用dbcc useroptions查看可以看到事務隔離級別被全局的修改成了read committed snapshot。

ALTER DATABASE [dbname] SET READ_COMMITTED_SNAPSHOT ON;

兩者的區別在於:

READ_COMMITTED_SNAPSHOT是指Select語句總是讀取最新的已提交的數據,即如果有DML事務正在執行,那麼select語句不會被阻塞而是讀取這些DML事務預先生成的前鏡像,這種讀只會在表上加Sch-S鎖,其他的行鎖頁鎖全部沒有。DML數據一旦提交,再次執行Select語句就會立馬讀到新的數據。

SNAPSHOT隔離級別與上述的區別在於,如果你在同一個事務內執行兩次相同的select語句,那麼即便在這兩次select語句之間發生了數據更改且提交,兩次讀到的數據也是一樣的。

用官網的一句話來描述兩者區別就是:READ_COMMITTED_SNAPSHOT提供語句級的一致性,SNAPSHOT事務隔離級別提供事務級的一致性。

五、全部6種隔離級別的加鎖模式:

開始說過事務隔離級別主要就是控制讀操作加什麼鎖,鎖占用多長時間的的,因此只有搞清各事務隔離級別下的加鎖機制才能徹底搞清事務隔離級別的概念和他們的不同。

1.未提交讀

未提交讀不對讀取的數據加鎖,因此不會造成阻塞,也會有臟讀出現,相當於為select語句添加了with nolock選項。

2.已提交讀

已提交讀對讀取的數據正常加鎖,但是不等事務結束才釋放鎖,而是讀完一個頁就會釋放,因此可能出現重覆讀和幻讀。這是SQL Server和Oracle的預設事務隔離級別。Oracle的實現更加完美,對Oracle資料庫來說,select操作不加鎖,因此不會出現讀阻塞寫,但SQL Server有可能。

3.已提交讀快照

SQL Server特有的隔離級別,主要是為了匹配Oracle的已提交讀實現的功能,在此隔離級別下,讀操作只會對錶加一個Sch-S鎖,因此讀操作不會引發在阻塞,但是會加大tempdb的使用量。

4.快照

同上,讀操作也只加Sch-S鎖,唯一區別在於實現的一致性讀是事務級別的,即快照在tempdb中保留的時間更長。

這裡猜測已提交讀快照隔離級別下快照的撤銷是DML事務結束後,而快照讀隔離級別下快照的撤銷是select事務結束後。

5.可重覆讀

可重覆讀加的鎖與已提交讀完全一致,區別在於只有在整個事務完成後才會釋放鎖,而不是讀完一個頁就釋放,此種加鎖方式也避免了不可重覆讀,因為事務期間其他DML無法獲取資源上的鎖。

6.序列化讀

序列化讀加的鎖與已提交讀有區別,此隔離級別下讀操作對索引鍵加的是鍵範圍鎖,而不是普通的S、U、X、IS、IU、IX等。

鍵範圍鎖的機制基本與Mysql中的範圍鎖一致,主要是為了防止幻讀,其機制在於select操作不但會將讀到的鍵值鎖定,還會將上下鍵值的範圍也鎖定。

舉例如下:

有主鍵為1,5,8,9,10的記錄,select ... where col between 3 and 7;會使用鍵範圍鎖將5這條記錄鎖定,除此之外還會用一個鍵範圍鎖將346這幾個虛幻的記錄也鎖定,這樣就不能在讀取操作期間插入數據了,可以防止幻讀。

Ps:對於序列化加的鍵範圍鎖是否是我上邊所說的那麼精確,還需要具體實驗,這裡只是根據官網猜測會使用多餘的一個鍵範圍鎖鎖定可能造成幻讀的記錄(總的鍵範圍鎖數目為n+1個,n為滿足查詢條件的行數),具體實驗方法參見我的另一篇博客,有興趣的可以試試。

http://www.cnblogs.com/leohahah/p/7059852.html

參考文檔:

https://docs.microsoft.com/zh-cn/sql/t-sql/statements/set-transaction-isolation-level-transact-sql

https://msdn.microsoft.com/zh-cn/library/jj856598(v=sql.120).aspx


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1增加主機映射(與namenode的映射一樣): 增加最後一行 2新建用戶hadoop 建立hadoop用戶組 新建用戶,useradd -d /usr/hadoop -g hadoop -m hadoop (新建用戶hadoop指定用戶主目錄/usr/hadoop 及所屬組hadoop) pass ...
  • 單個 節點 可以作為一個運行中的 Elasticsearch 的實例。 而一個 集群 是一組擁有相同 cluster.name 的節點, 他們能一起工作並共用數據,還提供容錯與可伸縮性。(當然,一個單獨的節點也可以組成一個集群) 你可以在 elasticsearch.yml 配置文件中 修改 clu... ...
  • ceiling函數返回大於或等於所給數字表達式的最小整數。 floor函數返回小於或等於所給數字表達式的最大整數。 eg: select ceiling(4.42) 5select CEILING(0.1) 1 select FLOOR(0.1)--0select FLOOR(4.42) 4 註意: ...
  • 索引 其實資料庫中的數據是按頁存放的其實索引也是按頁存放的所以本質上索引也占硬碟空間(以最小的消耗,換取最大的利益) 索引是一種有效組合數據的方式!為快速查找到指定記錄做鋪墊 目的就是快速或者某個記錄! 提高了資料庫的檢索速度!作用:大大提高資料庫的檢索速度改善資料庫性能 MySQL索引存儲類型分類 ...
  • 鎖相容性圖: 一、鎖的粒度: 比較需要註意的是RID/KEY、HoBT/PAGE這兩對兒的區別,RID和HoBT是針對堆表的,即沒有聚集索引的表。 二、鎖的模式: 1.關於其中的S、U、X鎖: 共用鎖 共用鎖(S 鎖)允許併發事務在封閉式併發控制下讀取 (SELECT) 資源。 資源上存在共用鎖(S ...
  • 存儲常式是存儲在資料庫伺服器中的一組sql語句,通過在查詢中調用一個指定的名稱來執行這些sql語句命令. 簡介 SQL語句需要先編譯然後執行,而存儲過程(Stored Procedure)是一組為了完成特定功能的SQL語句集,經編譯後存儲在資料庫中,用戶通過指定存儲過程的名字並給定參數(如果該存儲過 ...
  • Hadoop集群部署,就是以Cluster mode方式進行部署。本文是基於JDK1.7.0_79,hadoop2.7.5。 1.Hadoop的節點構成如下: HDFS daemon: NameNode, SecondaryNameNode, DataNode YARN damones: Resou ...
  • 基於記憶體的Redis應該是目前各種web開發業務中最為常用的key-value資料庫了,我們經常在業務中用其存儲用戶登陸態(Session存儲),加速一些熱數據的查詢(相比較mysql而言,速度有數量級的提升),做簡單的消息隊列(LPUSH和BRPOP)、訂閱發佈(PUB/SUB)系統等等。規模比較 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...