Sql Server中的事務與事務隔離級別

来源:http://www.cnblogs.com/caoshiqing/archive/2017/08/10/5674286.html
-Advertisement-
Play Games

事務是資料庫進行併發控制非常重要的機制,通過本文來系統的瞭解一下事務到底是怎麼回事。 1、什麼是事務? 事務是作為單個邏輯工作單元執行的一系列操作,它由一條或者一組語句組成,它們麽全部成功,要麼全部失敗。 舉個例子,比如在12306訂火車票,要麼你訂票成功,餘票顯示就減少一張;要麼你訂票失敗,餘票顯 ...


  

  事務是資料庫進行併發控制非常重要的機制,通過本文來系統的瞭解一下事務到底是怎麼回事。

1、什麼是事務?

  事務是作為單個邏輯工作單元執行的一系列操作,它由一條或者一組語句組成,它們麽全部成功,要麼全部失敗。

  舉個例子,比如在12306訂火車票,要麼你訂票成功,餘票顯示就減少一張;要麼你訂票失敗,餘票顯示還是那麼多。不允許出現你訂票成功了,餘票卻沒有減少的情況。那麼這種購票和餘票減少的兩個不同的操作必須放在一起,成為一個完成的邏輯,這樣就構成了一個事務。

2、事務有哪些特性?

  原子性(Atomicity): 原子性是指一個是事務中包含的一條語句或者多條語句構成了一個完整的工作單元,那麼這個工作單元要麼一起提交執行全部成功,要麼執行全部失敗;

   一致性(Consistency):可以理解為數據的完整性,它用來保證數據從一個一致性的狀態變成另外一個一致性的狀態,比如賬戶A給賬戶B轉賬100元,那麼賬戶A應該減少100元,賬戶B增加100元,但是兩人錢數總和還是沒變的;

  隔離性(Isolation):一個事務的所做的修改不能被其他的事務影響,讀取到的數據狀態要麼是事務開始前的,要麼是事務結束後的;

  持久性(Durability):事務一旦對數據的操作完成後,數據修改就已經完成了。

3、事務的分類?

  事務有三種常見的類型:

  自動提交事務:sql server 的預設事務類型,每條單獨的SQL語句都是單獨的一個事務,語句執行完畢自動提交,錯誤則自動回滾;

  顯示事務:顯示的聲明事務的開始(BEGIN TRANSACTION)和結束(COMMIT TRANSACTIOIN或ROLLBACK TRANSACTION);

  隱式事務:使用 SET IMPLICIT_TRANSACTIONS ON語句啟動隱式事務,使用SET IMPLICIT_TRANSACTIONS OFF 關閉隱式事務,但不會像自動模式那樣自動執行ROLLBACK或COMMIT語句,隱式事務必須顯示結束(COMMIT或ROLLBACK);

4、事務隔離級別

  隔離級別是用來限制一個事務中正在讀取或被修改的數據免於被其他事務修改的程度。

  理論上每個事務和其他的事務都應該完全隔離開來。然而出於性能和可行性的原因,實踐中幾乎不可能做到的。在併發環境下如果沒有鎖和隔離級別,可能會發生以下四種情況:

  臟讀:在這種情況下,一個事務能夠讀取另一個事務正在修改且未提交的數據,那麼另一個事務如果發生回滾操作,將導致第一個事務讀取到的數據和實際的數據不一致;

  丟失更新:這種情況下,事務沒有隔離。多個事務能夠讀取同一份數據並且修改它。最後對數據集做出修改的事務將勝出,而其他的事務所做的修改都失效;

  不可重覆讀:兩個事務讀取數據,但是在第二個事務讀取前,另一個事務修改了該數據,因此兩次讀取的數據不一致;

  幻讀:這種情況和不可重覆讀類似,不同的是,兩個事務讀取一個範圍的數據,但是在第二個事務讀取之前,另一個事務新增了一條數據,導致兩次讀取的結果不同。

  在瞭解了併發情況下出現的上述問題後,就可以進一步理解隔離級別的概念,通俗一點講就是:你希望以何種方式將併發的事務隔離開來, 隔離到什麼程度?比如允許臟讀,等。隔離級別越高,讀取臟數據或者造成數據不一致的情況就越少,但是在高併發系統中的性能降低就越嚴重。

  Sql Server 2008支持6種隔離級別:

  • 未提交讀(Read Uncommited)
  • 已提交讀(Read Commited)
  • 可重覆讀(Repeatable Read)
  • 序列化(Serializable)
  • 快照(Snapshot)
  • 已提交讀快照(Read Commited Snapshot)

  下麵我們通過代碼來演示各個事務隔離級別的表現:

  未提交讀(Read Uncommited)

  隔離級別最低,允許一個事務讀取其他事務修改但未提交的數據,也就是會產生“臟讀”的問題,它的作用和SELECT語句在對象表上設置(NOLOCK)相同。

  打開兩個查詢視窗,下麵第一個表示事務A,第二個表示事務,事務A保持預設隔離級別,事務B設置為Read Uncommitted,先執行事務A,接著執行事務B;

語法:SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

     DBCC USEROPTIONS ---查看當前設置

  事務A:

  

 

  事務B:

  

 從圖中可以看出,事務B對同一條數據讀取了兩次,但很明顯第一次讀到的數據是“臟數據”

  已提交讀(Read Committed)

  這是Sql Server的預設隔離級別,一個事務不允許讀取另一個事務未提交的數據,Read Committed可以有效的防止“臟讀”的出現,但是能夠讀取由其他事務修改並提交的數據,也就是說,有可能會出現“不可重覆讀”和“幻讀”的問題。

  接著上一個例子,我們把事務B的隔離級別設置為Read Committed,來看一下執行情況,還是先執行事務A,再接著執行事務 B;

  事務A:

  

  事務B:

  

  在當前隔離級別下,當事務B讀取數據時,事務B必須等待事務A結束以後才能讀取,但是也有可能會出現其他問題,請看例子。先執行事務A,接著執行事務B。

    

   從上圖中可以看的出來,事務A讀第一次查詢後,事務B對數據進行了修改,導致事務A兩次查詢不一致,因此出現了“不可重覆讀”的情況,那麼怎麼避免呢,接著往下看

   可重覆讀(Repeatable Read)

 一個事務讀取的數據在未結束之前,不能被其他事務修改,這個隔離級別可以解決“不可重覆讀”的問題

  

通過結果我們可以看出事務A兩次讀取的數據時一致的 ,那麼如果把事務B的修改換成插入呢,修改上面的示例:

通過運行結果我們發現,事務A兩次讀取的結果集不一樣了,這就是幻讀。那麼我們繼續看下一個隔離級別 

序列化(SERIALIZABLE)

這是最高級別的隔離,它會鎖定一個範圍的數據,從而阻止其他事務修改或新增這個範圍的數據,修改上面的例子,依然是先執行事務A,在執行事務B

從執行結果可以看出,事務A兩次讀取數據的結果是一致的,事務B明顯是等待事務A結束後才執行完成的,雖然序列化隔離級別更高,也可以很好的避免併發產生的問題,但是同時也降低了數據的可用性。

 

另外兩個隔離級別是基於行版本的隔離級別

快照(SNAPSHOT)

通過在事務開始前在tempdb中創建一份資料庫的虛擬快照,此後它只允許事務訪問該資料庫的虛擬快照,但是如果當前快照事務修改已經由其他事務修改的數據,將導致錯誤並終止,預設情況下SNAPSHOT隔離級別在資料庫中是不啟用的,那麼需要使用ALTER DATABASE test SET ALLOW_SNAPSHOT_ISOLATION ON啟用

只有當資料庫中啟用SNAPSHOT事務隔離級別的開關打開後,才能使用它。打開此開關將告知資料庫去設置版本化環境。理解這一點很重要,因為,一旦版本化開啟,資料庫會有維護版本化的開銷,無論是否有事務正在使用SNAPSHOT事務隔離級別。

提交讀快照(READ COMMITTED SNAPSHOT)

提交讀快照和快照隔離級別是類似的,不同的是:

  • 通過ALTER DATABASE Test SET READ_COMMITTED_SNAPSHOT ON 來開啟資料庫提交讀快照,運行這句話的時候不能有其他連接到當前DB;
  • 已提交讀啟用後,READ_COMMITTED事務會通過使用行版本提供數據讀取的一致性;
  • 在其他事務修改提交後可以讀取到修改的數據,而快照事務在當前事務未重新開始前讀取的都是快照數據;
  • 能夠更新由其他事務修改的數據,而快照事務不能;

針對這兩種隔離級別的測試,有興趣的話可以自己試一下。

五、總結

隔離級別 解決併發問題 存在的併發問題  說明
READ UNCOMMITED   不適用於併發場合  臟讀、不可重覆讀、幻讀  隔離級別最低,允許一個事務讀取其他事務修改但未提交的數據
READ COMMITED   臟讀  丟失更新、不可重覆讀、幻讀  這是Sql Server的預設隔離級別,一個事務不允許讀取另一個事務未提交的數據
REPEATABLE READ 不可重覆讀 幻讀、死鎖   一個事務讀取的數據在未結束之前,不能被其他事務修改
SERIALIZABLE 幻讀    數據可用性降低、死鎖 這是最高級別的隔離,它會鎖定一個範圍的數據,從而阻止其他事務修改或新增這個範圍的數據 
SNAPSHOT 上述所有併發問題    事務訪問的是虛擬快照,其他事務Commited的數據對當前事務仍然不可見,也不允許Update被其他事務Update的數據 快照事務隔離級別預設是不啟用的,是基於行版本的事務控制
 READ COMMITTED SNAPSHOT    上述所有併發問題  無  它可以讀取被其他事務提交的數據,也可以修改數據

 

 

 

 

 

 

 

 

 

   

 

  

 

  

  

  

 

 

  


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

-Advertisement-
Play Games
更多相關文章
  • 連載上一篇http://www.cnblogs.com/hackfun/p/7327320.html (D) 如何載入訪問.so庫 在前一篇博客http://www.cnblogs.com/hackfun/p/7327320.html中,知道如何生成了一個HAL的.so庫,在這裡將分析如何載入這個H ...
  • 在mac上的ionic3項目打包成蘋果app,系統版本是10.3.3 . 當調用相機的時候出現閃退情況,這是調試出現的問題: This app has crashed because it attempted to access privacy-sensitive data without a us ...
  • 在mac上,cordova打包ionic項目為蘋果手機app出現 這個問題:ERROR Internal navigation rejected - <allow-navigation> not set for url='about:blank' 解決方案: 出現這個錯誤的原因是因為沒有設置白名單打 ...
  • iOS精選源碼 自己維護的框架, 超級多功能 圖片選擇SDK:支持多選,相冊選擇,預覽,網路圖預覽 一款可以簡單實現長按拖拽重排的 UICellCollectionView Cell框... 動畫引擎 FXAnimationEngine MJCIOS/MJCSegmentInterface(分段界面 ...
  • 一,效果圖。 二,代碼。 ViewController.m ...
  • 當遇到資料庫占用空間很大的情況下,可以用以下語句查找大數據量的表 運行結果 ...
  • 索引分析 單表 創建表並插入數據 查詢語句(查詢category_id為1 且comments大於1的情況下view最多的author_id) sql分析 結果:type為All(變數全表)即最壞的情況,Extra里還出現了using filesor(文件排序)即使用一個外部的索引排序情況也是最壞所 ...
  • DDL(data definition language)創建和管理表 1.創建表 1.直接創建 2.通過子查詢的方式創建 2.修改表 1.增加新的列 2.修改現有的列 3.重命名現有的列 4.刪除現有的列 3.清空表中的數據 4.重命名錶 5.刪除表 DML(data manipulation l ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...