SQL Server 中的6種事務隔離級別簡單總結

来源:http://www.cnblogs.com/wy123/archive/2017/07/22/7218316.html
-Advertisement-
Play Games

本文出處:http://www.cnblogs.com/wy123/p/7218316.html (保留出處並非什麼原創作品權利,本人拙作還遠遠達不到,僅僅是為了鏈接到原文,因為後續對可能存在的一些錯誤進行修正或補充,無他) 資料庫中的事物是具有原子性(Atomicity),一致性(Consiste ...


 

本文出處:http://www.cnblogs.com/wy123/p/7218316.html 
(保留出處並非什麼原創作品權利,本人拙作還遠遠達不到,僅僅是為了鏈接到原文,因為後續對可能存在的一些錯誤進行修正或補充,無他)

 


資料庫中的事物是具有原子性(Atomicity),一致性(Consistemcy),隔離性(Isolation),持久性(Durability)四個特征。
在上述四個特性中的一致性和隔離性的實現中,是通過鎖來實現對相同數據的訪問隔離的。
事物的隔離級別又可以影響鎖的申請和時間的時機。
因此,不同的事物隔離級別又可以對鎖的申請和釋放產生不同的影響,因此,在對資料庫做事物控制的時候需要瞭解隔離級別對事物的影響。
SQL Server實現SQL99標準規定的事務的四個隔離級別(未提交讀,已提交讀,可重覆讀,序列化)之外,另外增加了兩個隔離級別(快照個基於行版本的已提交讀隔離級別)。
不同的隔離級別對控制臟讀,不可重覆讀,幻讀有一定的控制,也會併發有一定程度的影響,
隔離級別越低,併發性越高,但是產生臟讀,不可重覆讀,幻讀等可能性越大;隨著事物隔離級別的提交,可以控制臟讀,不可重覆讀,以及幻讀的現象,但是併發性也會隨之降低。
事物隔離級別和執行計劃都可以影響鎖(範圍)的申請和釋放時機,本文暫不討論執行計劃對鎖申請的影響,僅在隔離級別上說明鎖的申請和釋放。
以下簡單介紹SQL Server中的六個隔離級別以及每個隔離級別的特征,在此基礎上說明每個隔離級別可能存在的問題解決方法。


未提交讀

運行當前Session讀取其他事務已修改但是尚未提交的數據,也即當前Session可以讀取到“臟數據”。
當前Session不會對讀取的數據加共用鎖。
set transaction isolation level read uncommitted;
或者
select * from table with(nolock)

特點:未提交讀是最低的一種隔離級別。
存在的問題:臟讀,不一致讀,幻讀等。


如下是未提交度的存在臟讀一種演示(當然也會存在不一致讀,幻讀等情況)。

   

 


已提交讀

set transaction isolation level read committed;
或者
select * from table  預設人就是已提交讀
運行當前Session不能讀取其他事務已修改但是尚未提交的數據。
如果其他事務提對當前Session讀取的數據有修改且尚未提交,當前Session被阻塞。
原因是在以已提交讀隔離級別情況下:當前Session會對讀取的數據加共用鎖,如果遇到讀取的數據尚未提交,當前查詢被阻塞。

特點:相比為提交讀隔離級別,解決了未提交讀隔離級別下的讀取“臟數據”的問題,
存在的問題:存在不可重覆度或者幻讀的問題。

 

已提交讀隔離級別下存在不可重覆讀的現象(兩次讀取的同一行數據結果不一致)

 

 

 不可重覆讀隔離級別下存在的幻讀現象(一個事物中,同樣的條件,讀到的數據行數不一致)

   

 


可重覆讀

set transaction isolation level repeatable read;
運行當前Session不能讀取其他事務已修改但是尚未提交的數據,並且當前Session運行期間,其他Session不能修改當前Session讀取到的數據
也就是說,當前Session運行期間,讀取到的數據是被加了共用鎖的,所加的共用鎖一直保持,直到事務提交的時候才釋放。
相比已提交讀最大的特點就是事務運行期間,共用鎖將一直保持,直到當前Session事務提交,
因此可以保持當前Session讀取到的數據不被其他Session修改,所以就不存在兩次讀取的數據不一致的現象。
可重覆讀隔離級別解決了不可重覆讀的問題,但依舊存在幻讀的情況。

特點:相比前一種隔離級別,可重覆讀解決了已提交讀隔離級別的不可重覆讀的問題,也即兩次讀取的同一行數據是一致的
存在的問題:相比已提交讀,依舊存在幻讀的問題。

 

  如下是可重覆讀隔離級別的幻讀的現象,也即在同一個事物的兩次讀取期間,其他事物可以寫入當前事物讀取的數據(範圍)

  


可序列化

當前Session不能讀取其他Session已修改但未提交的數據(不允許臟讀)
當前Session讀取的數據上的共用鎖一直保持直到事務提交(可重覆讀)
當前Session事務提交之前,其他Session不能插入當前Session中讀取的鍵值(解決了幻讀的問題)
set transaction isolation level serializable
或者開啟事務之後對錶加holdlock提示
select * from table with(holdlock) where id = n
可序列化解決了另外一個非常經典的問題,使用update table with(holdlock) 或者select * from table with(xlock,holdlock),併發情況下的“存在則更新不存在則插入”重覆插入的問題。
參考:http://www.cnblogs.com/TeyGao/p/6929246.html

可序列化鎖定的原理是加範圍鎖的方式來實現的,當一個Session發起了請求之後,對於當前Session範圍內的數據,不管是否存在,都加一個共用鎖。
比如在可序列化的隔離級別之下,select * from table with where id>=100 and id<= 120
在Session執行期間,SQL Server會鎖定 100<=id<= 120這個範圍的數據,不管表中這個區間是否存在數據, 都鎖定這個Id的範圍,不允許該Id範圍的數據寫入。
也即100<=id<= 120這個範圍被所鎖定(無法增加刪除或者修改這個範圍的數據)

 

可序列化隔離級別解決了幻讀的問題,也就是說,當前事物的兩次讀中間,其他Session對當前Session讀取數據範圍之內的數據修改的時候,會被阻塞,直到當前事物提交。

   

 

 

基於行版本控制的隔離級別

  預設隔離級別,也即已提交讀隔離級別下,存在一個明顯的問題就是寫會阻塞讀,也就是說,一個寫數據的事物未提交之前,會阻塞其他事物對當前操作數據的讀取,直到當前寫事物的操作提交。
  基於行版本控制的已提交讀隔離級別下,寫不會阻塞讀,寫數據的事物未提交之前,會將修改的數據之前的版本,寫入臨時資料庫,
  讀數據的事物在讀取的時候,發現要讀取的數據被修改,會轉向臨時庫中讀取出來一個寫事物修改數據之前的版本,這樣可以在一定程度上提高併發性(當然臨時庫會承擔一定的壓力)。
  SQL Server有兩種基於行版本控制的隔離級別:快照隔離級別(snapshot)和基於行版本控制的已提交讀隔離級別(read_committed_snapshot)
     兩種行版本控制分別要基於數據級別開啟allow_snapshot_isolation和read_committed_snapshot

(1)快照隔離級別(snapshot)

資料庫級別設置快照隔離級別
alter database Test set allow_snapshot_isolation on;

 

 Session級別設置快照隔離級別:set transaction isolation level snapshot

 

快照隔離級別最大的特點是,當前Session讀取其他事物修改的數據的時候,不會被阻塞,讀取的是其他事物已經修改,但是尚未提交的數據
但是當前事物嘗試修改“在其他其他事物中提交修改之後的數據”,會報錯。
具體過程如下,從時間的維度來看,步驟如下
1)Session2 開啟事物,修改Id =1的數據,暫不提交
2)Session1 讀取id=1的數據,不會被阻塞,讀取到的是Session2修改之前的數據的版本
3)Session2修改Id =1的數據之後,事物提交
4)Session1嘗試修改Id=1的數據,報錯

  

  實際操作上看,如下

 

(2)基於行版本控制的已提交讀隔離級別(read_committed_snapshot)

資料庫級別設置為基於行版本控制的已提交讀隔離級
alter database Test set read_committed_snapshot on;
go


--將當前事物設置為已提交讀快照隔離級別
set transaction isolation level read committed

快照隔離級別最大的特點是,當前Session讀取其他事物修改的數據的時候,不會被阻塞,讀取的是其他事物已經修改,但是尚未提交的數據
與快照隔離級別相對,當前Session嘗試修改“在其他其他Session中提交修改之後的數據”,可以成功提交。
具體過程如下,從時間的維度來看,步驟如下
1)Session2 開啟事物,修改Id =1的數據,暫不提交
2)Session1 讀取id=1的數據,不會被阻塞,讀取到的是Session2修改之前的數據的版本
3)Session2修改Id =1的數據之後,事物提交
4)Session1嘗試修改Id=1的數據,成功提交,

  基於行版本控制的已提交讀隔離級別最大的特點是,當前讀取的數據是,其他Session已修改尚未提交之前的版本,但是當前事物嘗試修改時,可以成功提交
  這樣一來,就忽略掉了當前事物運行期間,其他事物修改且提交的那個版本的數據,有點繞,需要慢慢理解。

  行版本控制的已提交讀隔離級別的問題也很明顯,當前Session讀取數據的時候,是其他事物修改之前的版本,當前Session對讀取到的數據可以在其他事物提價之前的版本上執行修改,
  而忽略了當前Session在讀和寫的間隔期間,其他Session修改並且提交事物的影響,為此可能會產生一定程度的影響。

 

   從時間維度上看如下圖所示

 

 

具體執行現象如下:
存在的問題就是,Session1第一次讀取的時候,讀取的Id = 1數據的那麼是AAA,實際上此時其他Session2已經將Id = 1的那麼修改為了Update_AAA,
隨後Session2事物提交,當前Session執行修改的時候,忽略了Session2修改後的數據,可以直接將數據修改為AAA+++
需要註意的是,Session1修改成功的前提是Session2的事物提交,如果Session2修改事物沒有提交,Session1的修改操作被阻塞。

截圖中第一行的備註沒有修改過來,應該是快照已提價讀隔離級別

   

  

 總結:

  本文簡單闡述了SQL Server中的幾種隔離級別,SQL Server實現了SQL99定義的四個標準隔離級別,並且額外實現了兩個快照隔離級別。
  需要說明的是,不同的DBMS的預設隔離級別和對隔離級別的實現是不完全一樣的,也不一定是完全按照SQL99定義的四個標準隔離級別來實現的,
  因此在做事物控制的時候,需要瞭解具體的隔離級別以及具體特性。


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

-Advertisement-
Play Games
更多相關文章
  • #列印實心菱形,思路:分上下,i控制行,j控制列印的空格數,k控制列印的*數量row = int(input("please input a raw number: "))for i in range(row): #i控制行數 for j in range(row-1-i):#空格數和行數的關係 p ...
  • XML文件處理 XML文件處理,有好幾種方式,這裡介紹一下xml.etree.ElementTree as ET。 註意:xml.etree.ElementTree模塊在應對惡意結構數據時顯得並不安全。 每個element對象都具有以下屬性: 1. tag:string對象,表示數據代表的種類; 2 ...
  • 一.ServletContext 介面(javax.servlet)定義:public interface ServletContext原理: Tomcat啟動的時候,需要識別webapps下的各個WEB應用,識別各個WEB應用的同時為每個WEB應用創建對應的對象ServletContext,一個W... ...
  • 最近在做ProtoBuf相關的項目,其中用到了動態解析,網上看了下相關資料和博文都比較少,自己來寫一個記錄一下學習過程。 Protocol Buffers是結構化數據格式標準,提供序列化和反序列方法,用於存儲和交換。語言中立,平臺無關、可擴展。目前官方提供了C++、Java、Python API,也 ...
  • 設計模式之單列模式 1,何為單列模式? 即singleton 在某個類採用了單列模式之後 其只能有一個實列對象 ,並且這個實列對象只能有內部自己創建並提供給外部的調用。 2.實現單列模式的方法 分為 :餓漢式 ,懶漢式 下麵為餓漢式實現代碼: 餓漢式 通過創建一個靜態成員變數 在類載入的時候直接創建 ...
  • thinkphp的CBD模式 核心保留了最關鍵的部分,併在重要位置設置了標簽用以標記,其他功能都採用行為擴展和驅動的方式組合,開發人員可以根據自己的需要,對某個標簽位置進行行為擴展或者替換,就可以方便的定製框架底層,也可以在應用層添加自己的標簽位置和添加應用行為。而標簽位置類似於AOP概念中的“切麵 ...
  • 1:項目場景 在設計數據表的時候有時候為了將來統計或查詢的方便,我們會冗餘一些欄位。如有三張數據表,學校信息表、班級動態表、班級信息表。 班級動態由學校老師所發,可以進行評論點贊等操作,為了提升這種非結構化數據的訪問效率,存儲於Mongodb中,冗餘了學校名稱欄位,假設班級表也冗餘了學校名稱欄位。而 ...
  • 1. 卓聘IM開發背景 智聯卓聘是智聯旗下高端人才招聘平臺,成立快4年了,業務增漲每年以100%速度增漲,業務增漲快在開發和上線速度要求也比較高。 2016年6月提出IM開發需求,7月初上線,開發人員三名,開發時間20多天,後期可以不斷滿足業務需求。前期階段我們考慮網上各種提供IM的雲平臺,這些平臺 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...