資料庫的快照隔離級別(Snapshot Isolation)

来源:http://www.cnblogs.com/ljhdo/archive/2016/12/24/5037033.html
-Advertisement-
Play Games

隔離級別定義事務操作資源和更新數據的隔離程度,在SQL Server中,隔離級別隻會影響讀操作申請的共用鎖,而不會影響寫操作申請的互斥鎖。隔離級別控制事務在執行讀操作時: 在讀數據時是否使用共用鎖,申請何種類型的隔離級別; 事務持有讀鎖的時間 讀操作引用其他事務更新的數據行時,控制讀操作的行為: 被 ...


隔離級別定義事務操作資源和更新數據的隔離程度,在SQL Server中,隔離級別隻會影響讀操作申請的共用鎖,而不會影響寫操作申請的互斥鎖。隔離級別控制事務在執行讀操作時:

  • 在讀數據時是否使用共用鎖,申請何種類型的隔離級別;
  • 事務持有讀鎖的時間
  • 讀操作引用其他事務更新的數據行時,控制讀操作的行為:
    • 被阻塞,等待其他事務釋放互斥鎖;
    • 讀取事務提交後的版本,該數據行在事務開始時存在;Retrieves the committed version of the row that existed at the time the statement or transaction started.
    • 讀沒有提交的數據;

在執行寫操作時,事務持有互斥鎖,直到事務結束才釋放,互斥鎖不受事務隔離級別的影響。隔離性和併發性是此消彼長的關係。在SQL Server中,互斥鎖和任意鎖都不相容,在同一時間,同一個數據行上,只能有一個事務持有互斥鎖,就是說,寫操作是順序進行的,不能併發。

Choosing a transaction isolation level does not affect the locks acquired to protect data modifications. A transaction always gets an exclusive lock on any data it modifies, and holds that lock until the transaction completes, regardless of the isolation level set for that transaction. 

事務的隔離級別共有5個,使用SET命令修改Session-Level的隔離級別,使用DBCC UserOptions 查看當前Session的隔離級別:

SET TRANSACTION ISOLATION LEVEL
     READ UNCOMMITTED
    | READ COMMITTED
    | REPEATABLE READ
    | SNAPSHOT
    | SERIALIZABLE

DBCC UserOptions
View Code

一,事務的隔離級別

SQL Server 預設的隔離級別是Read Committed,用戶不能修改Database-Level預設的隔離級別,但能夠修改Session-Level預設的隔離級別。Session-Level預設的隔離級別是Read Committed,該隔離級別受到資料庫選項 READ_COMMITTED_SNAPSHOT 的影響,決定Read Committed隔離級別是否使用行版本控制事務的讀操作,在Read Committed隔離級別下:

  • 如果設置選項READ_COMMITTED_SNAPSHOT為OFF,那麼事務在執行讀操作時申請共用鎖,阻塞其他事務的寫操作;
  • 如果設置選項READ_COMMITTED_SNAPSHOT為ON,那麼事務在執行讀操作時使用Row Versioning,不會申請共用鎖,不會阻塞其他事務的寫操作;

在任何隔離級別下,事務在執行寫操作時都申請互斥鎖(exclusive lock),持有互斥鎖直到事務結束,互斥鎖不受隔離級別的控制;而共用鎖(Shared Lock)受到隔離級別的控制,隔離級別影響Shared Lock的申請和釋放:

  • 在 Read Uncommitted隔離級別下,讀操作不會申請Shared Lock;
  • 在 Read Committed(不使用row-versioning),Repeatable Read 和 Serializable隔離級別下,都會申請Shared Lock;
  • 在 Read Committed(不使用row-versioning) 隔離級別下,在讀操作執行時,申請和持有Share Lock;一旦讀操作完成,釋放Shared Lock;
  • 在 Repeatable Read 和 Serializable隔離級別下,事務會持有Shared Lock,直到事務結束(提交或回滾);

SQL Server支持使用Row Versioning的隔離級別,事務的讀操作只申請SCH-S 表級鎖,不會申請Page 鎖和Row 鎖:

  • 當資料庫選項 READ_COMMITTED_SNAPSHOT設置為ON,Read Committed隔離級別使用Row Versioning提供語句級別(Statement-Level)的讀一致性;
    • When a transaction runs at the read committed isolation level, all statements see a snapshot of data as it exists at the start of the statement. 
  • Snapshot隔離級別使用Row Versioning 提供事務級(Transaction-Level)的讀一致性。當讀取被其他事務修改的數據行時,獲取在當前事務開始時的行版本數據,使用Snapshot隔離級別時,必須設置資料庫選項ALLOW_SNAPSHOT_ISOLATION為ON;
    • When reading rows modified by another transaction, they retrieve the version of the row that existed when the transaction started.
  • 註意語句級別的讀一致性和事務級別的讀一致性是snapshot 和 read committed snpshot 最大的區別:
    • 事務級別的讀一致性是指:在事務開始,到事務提交期間,該事務持有表數據的一個快照。如果在該事務活動期間,其他事務更新表數據,該事務只會讀取快照數據,不會讀取到被其他事務更新的數據值;
    • 語句級別的讀一致性是指:事務持有的數據快照,在語句結束時,立即釋放;在事務活動期間,能夠讀取到其他事務提交更新的數據值;

二,使用Row Versioning的隔離級別

在預設的隔離級別Read Commited下,在執行讀操作時,事務申請shared lock,讀寫操作相互阻塞。在隔離級別Read Uncommitted下,事務不會申請shared lock,因此讀操作不會阻塞寫操作,但是讀操作可能會讀到臟數據。臟數據是指被其它尚未提交的事務修改之後的數據值,不是指更新之前的數據值。

SQL Server 提供Snapshot隔離級別,用於讀取修改之前的數據值。在Snapshot隔離級別下,事務在修改任何數據之前,先將修改前的數據複製到tempdb,寫操作創建數據行的一個原始版本(Row Version),註意,SQL Server只會複製被修改的數據行,對於未修改的數據行,不會保存行版本數據。後續其他事務的一切讀操作都去讀這個複製的行版本。在Snapshot隔離級別下,讀寫操作不會互相阻塞。使用行版本控制提高事務的併發性,但是有一個明顯的缺點,雖然用戶讀到的不是臟數據,但是數據可能正在被修改,很快就要過期。如果根據這個過期的數據做數據修改,可能會產生邏輯錯誤。

1,啟用Snapshot隔離級別

設置資料庫選項 ALLOW_SNAPSHOT_ISOLATION 為 ON,沒有改變Session-Level的事務隔離級別,需要修改Session-Level的事務隔離級別為SNAPSHOT,才能使用行版本數據

alter database current
set allow_snapshot_isolation on;

要想使用snapshot隔離級別,必須將當前Session的隔離級別修改Snapshot,這樣當前的事務才能訪問Row Versioning數據:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

2,資料庫選項READ_COMMITTED_SNAPSHOT(簡稱RCS)

使用Row-Versioning數據時,資料庫選項ALLOW_SNAPSHOT_ISOLATION必須設置為ON,將資料庫選項READ_COMMITTED_SNAPSHOT設置為ON,在預設的隔離級別Read Committed下,事務能夠訪問Row Versioning數據:

alter database current
set allow_snapshot_isolation on;

alter database current 
set read_committed_snapshot on;

前提是必須設置資料庫選項ALLOW_SNAPSHOT_ISOLATION為ON,一旦啟用RCS選項,在預設的Read Committed 隔離級別中,事務使用行版本(row versioning)代替加鎖,事務能夠訪問版本化的數據行。Read Committed Snapshot隔離級別保證語句級別的事務一致性,TSQL語句只能讀取在該語句開始時已經提交的數據。當前事務的讀操作不會阻塞其他事務的寫操作,當前事務讀取的是其他事務已提交修改的數據值。

When a transaction runs at the read committed isolation level, all statements see a snapshot of data as it exists at the start of the statement. Setting the READ_COMMITTED_SNAPSHOT ON option allows access to versioned rows under the default READ COMMITTED isolation level.

3,READ COMMITTED Snapshot隔離級別

在Read Committed 隔離級別下,事務不能讀取被其他事務修改,但尚未提交的數據,即只能讀取已提交更新的數據,READ COMMITTED隔離級別的行為受到資料庫選項:READ_COMMITTED_SNAPSHOT的影響:

  • 如果設置RCS選項為OFF(預設設置),資料庫引擎使用Shared Lock阻止其他事務修改當前事務正在讀取的數據;當讀取被其他事務修改,但尚未提交更新的數據行時,該讀操作將被阻塞;
    • If READ_COMMITTED_SNAPSHOT is set to OFF (the default), the Database Engine uses shared locks to prevent other transactions from modifying rows while the current transaction is running a read operation. The shared locks also block the statement from reading rows modified by other transactions until the other transaction is completed.
  • 如果設置RCS選項為ON,資料庫引擎使用行版本化(Row Versioning)的數據實現語句級別的一致性,不會阻塞其他事務的寫操作,但只能讀取已提交更新的數據
    • If READ_COMMITTED_SNAPSHOT is set to ON, the Database Engine uses row versioning to present each statement with a transactionally consistent snapshot of the data as it existed at the start of the statement. Locks are not used to protect the data from updates by other transactions.

4,快照隔離級別

SNAPSHOT 隔離級別指定在一個事務中讀取的數據是一致性的數據版本。在事務開始時,在表級別創建數據快照,只能識別其他事務已提交的數據更新。在事務開始之後,當前事務不會識別其他事務執行的數據更新。Sanpshot隔離級別實現事務級別的數據一致性。SQL Server 使用tempdb來存儲行版本化(row versioning)的數據,如果數據更新較多,存儲的行版本太多,會導致tempdb成為系統瓶頸。

Specifies that data read by any statement in a transaction will be the transactionally consistent version of the data that existed at the start of the transaction. The transaction can only recognize data modifications that were committed before the start of the transaction. Data modifications made by other transactions after the start of the current transaction are not visible to statements executing in the current transaction. The effect is as if the statements in a transaction get a snapshot of the committed data as it existed at the start of the transaction.

三,啟用快照隔離級別

1,使用snapshot 隔離級別

step1,設置資料庫選項

ALTER DATABASE CURRENT SET SINGLE_USER 
WITH ROLLBACK IMMEDIATE; ALTER DATABASE CURRENT SET ALLOW_SNAPSHOT_ISOLATION ON; --ALTER DATABASE CURRENT SET READ_COMMITTED_SNAPSHOT OFF; ALTER DATABASE CURRENT SET MULTI_USER;

step2,修改Session-Level的隔離級別為snapshot

set transaction isolation level snapshot

2,使用Read_Committed_Snapshot隔離級別

ALTER DATABASE CURRENT SET SINGLE_USER 
WITH ROLLBACK IMMEDIATE; 
ALTER DATABASE CURRENT SET ALLOW_SNAPSHOT_ISOLATION ON; 
ALTER DATABASE CURRENT SET READ_COMMITTED_SNAPSHOT ON; 
ALTER DATABASE CURRENT SET MULTI_USER;

四,引用徐海蔚老師的例子,測試隔離級別的行為

 

snapshot隔離級別不會阻塞其他事務的寫操作,該隔離級別忽略數據的修改操作,只讀取row versioning的數據,就是說,讀取到的是數據修改之前的版本,當snapshot事務嘗試修改由其他事務修改的數據時,產生更新衝突,寫操作異常終止。

read committed snapshot隔離級別,讀取行版本化的已提交數據:

  • 當其他事務未提交更新時,讀取行版本化的數據,即讀取修改之前的數據值;
  • 當其他事務提交數據更新後,讀取修改後數據值;
  • 由於該隔離級別不會申請共用鎖,因此不會阻塞其他事務的更新操作;
  • 能夠更新由其他事務修改的數據;

參考文檔:

Isolation Levels in the Database Engine

SQL SERVER – Difference Between Read Committed Snapshot and Snapshot Isolation Level


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

-Advertisement-
Play Games
更多相關文章
  • 在之前的博文《Android中使用ViewPager實現屏幕頁面切換和引導頁效果實現》和《Android中Fragment的兩種創建方式》以及《Android中Fragment與Activity之間的交互(兩種實現方式)》中我們介紹了ViewPager以及Fragment各自的使用場景以及不同的實現 ...
  • 不同於Windows 8應用,Windows 10引入了“漢堡菜單”這一導航模式。說具體點,就拿官方的天氣應用來說,左上角三條橫杠的圖標外加一個SplitView控制項組成的這一導航模式就叫“漢堡菜單”。 本文討論的是如何實現官方的這一樣式(點擊後左側出現一個填充矩形),普通實現網上到處都是,有需要的 ...
  • 一、概述 運行時變更就是設備在運行時發生變化(例如屏幕旋轉、鍵盤可用性及語言)。發生這些變化,Android會重啟Activity,這時就需要保存activity的狀態及與activity相關的任務,以便恢復activity的狀態。 為此,google提供了三種解決方案: 下麵會逐一介紹三種情況,其 ...
  • 當我們要在App實現功能:輸入地名,編碼為經緯度,實現導航功能。 那麼,我需要用到原生地圖中的地理編碼功能,而在Core Location中主要包含了定位、地理編碼(包括反編碼)功能。 在文件中導入 #import <CoreLocation/CoreLocation.h> 地理編碼: 地理反編碼: ...
  • 備註:oracle版本Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 說明:創建臨時表空間註意關鍵字和創建表空間有所差別,語句類似 關於創建語句解說請查看:http://blog.chinaunix.net/uid-20802110 ...
  • 1.地址 2.Units單位 1 配置大小單位,開頭定義了一些基本的度量單位,只支持bytes,不支持bit 2 對大小寫不敏感 3.includes包含 ...
  • 存儲過程語法、概念、介紹;如何處理並記錄複雜存儲過程中發生的錯誤 ...
  • 本文出處:http://www.cnblogs.com/wy123/p/6217772.html 字元串自身相加, 雖然賦值給了varchar(max)類型的變了,在某些特殊情況下仍然會被“截斷”,這到底是varchar(max)長度的問題還是操作的問題? 1,兩個不超過8000長度的字元串自身相加 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...