1. 程式人生 > >SQLServer事務的隔離級別

SQLServer事務的隔離級別

轉自:http://www.cnblogs.com/qanholas/archive/2012/01/02/2310164.html


資料庫
是要被廣大客戶所共享訪問的,那麼在資料庫操作過程中很可能出現以下幾種不確定情況。

更新丟失(Lost update

  兩個事務都同時更新一行資料,但是第二個事務卻中途失敗退出,導致對資料的兩個修改都失效了。這是因為系統沒有執行任何的鎖操作,因此併發事務並沒有被隔離開來。

髒讀(Dirty Reads

  一個事務開始讀取了某行資料,但是另外一個事務已經更新了此資料但沒有能夠及時提交。這是相當危險的,因為很可能所有的操作都被回滾。

不可重複讀(Non-repeatable Reads

  一個事務對同一行資料重複讀取兩次,但是卻得到了不同的結果。它包括以下情況:

  (1 事務T1讀取某一資料後,事務T2對其做了修改,當事務T1再次讀該資料時得到與前一次不同的值。

  (2 幻讀(Phantom Reads:事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的資料或者缺少了第一次查詢中出現的資料(這裡並不要求兩次查詢的SQL語句相同)。這是因為在兩次查詢過程中有另外一個事務插入資料造成的。

  為了避免上面出現的幾種情況,在標準SQL規範中,定義了4個事務隔離級別,不同的隔離級別對事務的處理不同。

 未授權讀取(讀未提交)(Read Uncommitted

):允許髒讀取,但不允許更新丟失。如果一個事務已經開始寫資料,則另外一個數據則不允許同時進行寫操作,但允許其他事務讀此行資料。該隔離級別可以通過排他寫鎖實現。

 授權讀取(讀提交)(Read Committed):允許不可重複讀取,但不允許髒讀取。這可以通過瞬間共享讀鎖排他寫鎖實現。讀取資料的事務允許其他事務繼續訪問該行資料,但是未提交的寫事務將會禁止其他事務訪問該行。

 可重複讀取Repeatable Read):禁止不可重複讀取和髒讀取,但是有時可能出現幻影資料。這可以通過共享讀鎖排他寫鎖實現。讀取資料的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

 序列化Serializable):提供嚴格的事務隔離。它要求事務序列化執行,事務只能一個接著一個地執行,但不能併發執行。如果僅僅通過行級鎖是無法實現事務序列化的,必須通過其他機制保證新插入的資料不會被剛執行查詢操作的事務訪問到。

  隔離級別越高,越能保證資料的完整性和一致性,但是對併發效能的影響也越大。對於多數應用程式,可以優先考慮把資料庫系統的隔離級別設為Read Committed,它能夠避免髒讀取,而且具有較好的併發效能。儘管它會導致不可重複讀、虛讀和第二類丟失更新這些併發問題,在可能出現這類問題的個別場合,可以由應用程式採用悲觀鎖或樂觀鎖來控制。

事務的隔離級別

SQL Server通過在鎖資源上使用不同型別的鎖來隔離事務。為了開發安全的事務,定義事務內容以及應在何種情況下回滾至關重要,定義如何以及在多長時間內在事務中保持鎖定也同等重要。這由隔離級別決定。應用不同的隔離級別,SQL Server賦予開發者一種能力,讓他們為每一個單獨事務定義與其他事務的隔離程度。事務隔離級別的定義如下:

· 是否在讀資料的時候使用鎖

· 讀鎖持續多長時間

· 在讀資料的時候使用何種型別的鎖

· 讀操作希望讀已經被其他事務排他鎖住的資料時,怎麼辦?在這種情況下,SQL Server可以:

· 一直等到其他事務釋放鎖

· 讀沒有提交的資料

· 讀資料最後提交後的版本

ANSI 99定義了4種事務隔離級別,SQL Server 2005能夠完全支援這些級別:

· 未提交讀 在讀資料時不會檢查或使用任何鎖。因此,在這種隔離級別中可能讀取到沒有提交的資料。

· 已提交讀 只讀取提交的資料並等待其他事務釋放排他鎖。讀資料的共享鎖在讀操作完成後立即釋放。已提交讀是SQL Server的預設隔離級別。

· 可重複讀 像已提交讀級別那樣讀資料,但會保持共享鎖直到事務結束。

· 可序列化 工作方式類似於可重複讀。但它不僅會鎖定受影響的資料,還會鎖定這個範圍。這就阻止了新資料插入查詢所涉及的範圍,這種情況可以導致幻像讀。

此外,SQL Server還有兩種使用行版本控制來讀取資料的事務級別(本章後文將詳細檢驗這些隔離級別)。行版本控制允許一個事務在資料排他鎖定後讀取資料的最後提交版本。由於不必等待到鎖釋放就可進行讀操作,因此查詢效能得以大大增強。這兩種隔離級別如下:

· 已提交讀快照 它是一種提交讀級別的新實現。不像一般的提交讀級別,SQL Server會讀取最後提交的版本並因此不必在進行讀操作時等待直到鎖被釋放。這個級別可以替代提交讀級別。

· 快照 這種隔離使用行版本來提供事務級別的讀取一致性。這意味著在一個事務中,由於讀一致性可以通過行版本控制實現,因此同樣的資料總是可以像在可序列化級別上一樣被讀取而不必為防止來自其他事務的更改而被鎖定。

無論定義什麼隔離級別,對資料的更改總是通過排他鎖來鎖定並直到事務結束時才釋放。

很多情況下,定義正確的隔離級別並不是一個簡單的決定。作為一種通用的規則,要選擇在儘可能短的時間內鎖住最少資料,但同時依然可以為事務提供它所需的安全程度的隔離級別。

已提交讀

SQL Server 2005中,已提交讀隔離級別是建立連線時的預設隔離級別。這個級別存在兩種型別:已提交讀和已提交讀快照隔離級別。應用哪種型別由資料庫選項定義。已提交讀級別會在讀資料之前等待,直到阻塞鎖被釋放。已提交讀快照級別會在資料被其他事務阻塞時使用行版本控制來讀資料最後一次提交的版本。

使用已提交讀級別:

BEGIN TRAN

SELECT

FirstName, LastName, EmailAddress

FROM

Person.Contact

WHERE

ContactID = 1

現在假設另一事務在事務開啟狀態下更改了EmailAddress。開啟第二個查詢視窗並執行以下批來UPDATE EmailAddress,但不提交事務:

USE AdventureWorks;

BEGIN TRAN

UPDATE

Person.Contact

SET

WHERE

ContactID = 1

這個UPDATE 語句會正常執行。一行受到了影響,即使資料在這個事務還沒有執行完之前已被查詢視窗1中的事務讀取。因為已提交讀級別並不會在事務結束前保持用於SELECT語句的共享鎖。共享鎖會在資料讀取之後立即被SQL Server釋放。需要一致讀的時候這將是一個問題。我們將下面的"獲取一致的可重複讀操作"實現。

現在切換到查詢視窗1並嘗試再次讀資料:

SELECT

FirstName, LastName, EmailAddress

FROM

Person.Contact

WHERE

ContactID = 1

由於SELECT語句被阻塞,因此這個查詢並沒有結束。SQL Server會嘗試在ContactID= 1的鍵上獲取一個共享鎖,但是由於在查詢視窗2中的UPDATE語句對其有一個排他鎖,因此這個操作不可能完成。雖然查詢視窗2處於已提交讀級別(由於您沒有更改預設級別),但排他鎖依然存在。這個阻塞將持續存在,因為資料更改的排他鎖會一直保持直到事務結束。

切換到查詢視窗2,讓查詢視窗1中的查詢繼續執行。鍵入並執行以下SELECT語句檢查資料庫中的授權和等待的鎖。

可以看一個狀態為WAIT的共享鎖。這是查詢視窗1中執行的查詢。它在等待查詢視窗2中的查詢,後者在同樣的資源上有一個排他鎖。

在查詢視窗2中執行一個ROLLBACK TRAN語句來回滾UPDATE語句。然後切換回查詢視窗1。可以看到,查詢視窗1中的查詢完成了,並且其結果與以前的一樣。查詢視窗2中的事務結束的時候,鎖被釋放了,以至查詢視窗1中的查詢不再被阻塞。由於查詢視窗2中的事務回滾,因此查詢視窗1中得到的結果是原來的資料。如果查詢視窗2中的事務被提交,則查詢視窗1中會得到新的資料作為結果。

在查詢視窗1中執行一個COMMIT TRAN語句並關閉所有的查詢視窗。

可以看出,在(預設)已提交讀級別中SQL Server會等到排他鎖釋放之後再進行讀操作,以此來獲取真正的提交資料。還可以看出,共享鎖會持續到資料被讀取之後,而排他鎖會持續到事務提交之後。在許多事務幾乎同時更改資料的時候這種行為可能會造成問題。在這些情況下,由於排他鎖造成的阻塞,讀資料會非常慢。但在有些情況下,使用最後提交的資料版本是恰當的。在這些情況下,可以將已提交讀級別更改為已提交讀快照級別。

如果要在視窗1讀取資料的話,可以使用這樣的方法:

SELECT

FirstName, LastName, EmailAddress

FROM

Person.Contact WITH (NOLOCK)

WHERE

ContactID = 1

讓它取消所有的鎖機制,那麼排他鎖也不會影響到這句查詢。

使用NOLOCK注意:在 SQL Server 中,NOLOCK 提示將啟用"未提交讀"行為。在 SQL Server Mobile 中,使用 NOLOCK 提示仍會賦予"提交讀"隔離級別。SQL Server Mobile 將維護資料副本,以確保可以讀取資料而不需要使用共享鎖幫助保護資料。

使用已提交讀快照級別

啟用已提交讀快照級別

USE master;

ALTER DATABASE AdventureWorks

SET READ_COMMITTED_SNAPSHOT ON

注意:設定 READ_COMMITTED_SNAPSHOT 選項時,資料庫中僅允許存在執行 ALTER DATABASE 命令的連線。在 ALTER DATABASE 完成之前,資料庫中不允許有其他開啟的連線。資料庫不必處於單使用者模式。

現在,執行以下程式碼開始一個事務並像前面一樣更改EmailAddress(但要讓事務處於開啟狀態):

USE AdventureWorks;

BEGIN TRAN

UPDATE Person.Contact

WHERE ContactID = 1;

開啟第二個查詢視窗並執行以下語句來讀取ContactID 1的列NameEmailAddress列。

USE AdventureWorks;

BEGIN TRAN

SELECT FirstName, LastName, EmailAddress

FROM Person.Contact

WHERE ContactID = 1;

返回了聯絡人Gustavo AchongEmailAddress [email protected],這是這一行最後提交的版本。不像沒有快照的已提交讀級別那樣,這個查詢不會被阻塞。關閉查詢視窗2並切換到查詢視窗1

執行以下語句來回滾事務並切換回已提交讀級別(這個查詢將等待直到關閉查詢視窗2)

ROLLBACK TRAN

GO

USE master;

ALTER DATABASE AdventureWorks

SET READ_COMMITTED_SNAPSHOT OFF

重要提示 這個隔離級別可以用於減少阻塞。但要意識到這是一個數據庫選項。當它發生了更改,將在資料庫系統中使用已提交讀級別的所有事務也會改變它們的行為。因此,只有在所有這些事務讀最後提交的資料版本與讀真正提交的資料版本在邏輯上同樣正確的時候,使用這種級別才是明智的。

獲取一致的可重複讀操作

已提交讀級別的一個缺點是,一個事務讀取的資料在事務執行期間可能被另一個事務更改。因此,在兩種已提交讀級別下,不能保證一致性讀。獲取一致性讀的意思是,在一個事務中,讀取的資料始終是一樣的。

1.  已提交讀在讀資料的時候使用共享鎖,但在讀操作完成後會立即釋放這個鎖。因此,其他事務可以更改剛被讀過的資料。

2.  已提交讀快照讀取最後一次提交的資料版本。當它第二次讀資料的時候,最後一次提交的版本可能由於第二個事務已經提交了對資料的更改而變成一個新版本。

在需要一致性讀的時候(例如對於報表),可能這種不一致性會導致問題。想象一下,您的事務通過資料計算了一些商業數值。在已提交讀級別中進行這種計算的時候,可能由於基礎資料在事務計算過程中發生了變化而導致這些值被錯誤計算。為了成功地執行這個計算,可以使用快照隔離級別。它會使用行版本管理來提供資料的提交版本,但與已提交讀快照不同的是,它總會提供在開始事務時最後提交的資料版本。因此,SQL Server始終會在整個事務執行過程中獲取同樣的資料。

使用快照隔離級別

快照隔離級別需要在資料庫中一次性地啟用。啟用之後,每個連線可以在需要的時候使用它。

USE master;

ALTER DATABASE AdventureWorks

SET ALLOW_SNAPSHOT_ISOLATION ON;

現在假設我們希望執行一些基於Sales.SalesOrderDetail表的報表,但需要一致性的讀操作。執行以下語句為事務啟用快照隔離級別並開始一個返回訂單行合計的事務。記住OrderTotal的值。

USE AdventureWorks;

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

BEGIN TRAN

SELECT 

相關推薦

sqlserver 事務隔離級別

SQL Server通過在鎖資源上使用不同型別的鎖來隔離事務。為了開發安全的事務,定義事務內容以及應在何種情況下回滾至關重要,定義如何以及在多長時間內在事務中保持鎖定也同等重要。這由隔離級別決定。應用不同的隔離級別,SQL Server賦予開發者一種能力,讓他們為每一個單獨事

mysql的事務隔離級別

too con jpg 級別 tran 開啟 數據行 修改 ges 原文地址:http://www.cnblogs.com/snsdzjlz320/p/5761387.html [Mysql]——通過例子理解事務的4種隔離級別 SQL標準定義了4種隔離級別,包括了一

事務隔離級別的理解

回滾 自己 避免 ron ref blank 提交 範圍 聯系 數據庫事務的隔離級別有4種,由低到高分別為Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事務的並發操作中可能會出現臟讀

mysql 不同事務隔離級別

結果 讀取 般的 lec 不同的 新增 比較 一次 基礎 repeatable read 在同一事務中,同一查詢多次進行時候,由於其他插入操作(insert)的事務提交,導致每次返回不同的結果集。 標準的repeatable read是允許幻讀的,因為這一級別只在讀取過的紀

數據庫事務的四大特性和事務隔離級別

簡單 個數 多個實例 tails ref 感覺 mvc 不能 變換 Reference: [1] http://www.cnblogs.com/fjdingsd/p/5273008.html [2] http://blog.csdn.net/fg2006/article/d

mysql事務隔離級別與鎖的關系

美團 enc 自己 ren 問題總結 關系 sql 事務 sql事務 其實操作了這麽久mysql一直也沒有把mysql中事務跟鎖的關系弄得特別清楚。然後搜到美團這篇文章,順便結合一下自己遇到的問題總結一下。 首先事務有四種隔離級別: Refere

mariadb事務隔離級別相關實驗

mariadb mysql 事務 關於SQL的隔離級別SQL標準定義了4類隔離級別,如下所示:1. Read Uncommitted (讀取未提交內容)在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因為它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之

數據庫事務隔離級別(轉)

事務隔離級別 transacti 隔離級別 二次 設置 新增 重寫 upload strong 1.什麽是事務,事務的特性是什麽? 在數據庫中事務是工作的邏輯單元,一個事務是由一個或多個完成一組的相關行為的SQL語句組成,通過事務機制確保這一組SQL語句所作的操作要麽都成功

數據庫事務的四大特性及事務隔離級別

account nbsp 用戶 rep 相互 轉賬 個數 提示 atomic 概要: 事務的四個特性:原子性、一致性、隔離性、持久性 事務不隔離帶來的問題:臟讀、不可重復讀、虛讀(幻讀) 事務隔離的級別:串行化(111)、可重復讀(110)、讀已提交(100)、讀未提

事務隔離級別

避免死鎖 數據庫 鎖定 兼容性 sans 關系數據庫 一段時間 cnblogs 模式 事務具有四個特征:原子性( Atomicity )、一致性( Consistency )、隔離性( Isolation )和持續性( Durability )。這四個特性簡稱為 A

mysql事務隔離級別

也有 超時 改變 提交 已提交 style pda 結果 多個實例 概念 隔離級別用於決定如果控制並發用戶如何讀寫數據的操作,同時對性能也有一定的影響作用。 臟讀:讀取未提交的數據; 不可重復讀(Non-repeatable read):在一個事務的兩次查詢之中

Spring事務隔離級別和傳播特性

我們 head ttr and frame 自己的 傳播行為 nag key 傳播行為 事務的第一個方面是傳播行為。傳播行為定義關於客戶端和被調用方法的事務邊界。Spring定義了7中傳播行為。 傳播行為 意義 PROPAGATION_MANDATORY

SQL Server 事務隔離級別詳解

完成 sql 事務 create 事務隔離 測試數據 span read type off SQL 事務隔離級別 概述 隔離級別用於決定如果控制並發用戶如何讀寫數據的操作,同時對性能也有一定的影響作用。 步驟 事務隔離級別通過影響讀操作來間接地影響寫操作;可以在回

事務隔離級別區分,未提交讀,提交讀,可重復讀

行修改 返回 數據庫 數據隔離 read 執行 strong 操作 復讀 事務隔離超通俗好懂的的講解 按照隔離的級別由低到高,越高的隔離,效率越差   0)、DEFAULT 默認隔離級別,由數據庫的數據隔離級別確定隔離級別 1)、READ_UNCOMMIYTTE

MySQL事務隔離級別詳解

默認 多少 bcf 結構 有一個 個數 ref tle eat 轉載自: MySQL事務隔離級別詳解 SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級一般支持更高的並發處理,並擁有更低的系統開銷。Read

事務隔離級別和mysql事務隔離級別修改

eat log control 容易 新的 pda mit 全局 nbsp A事務做了操作 沒有提交 對B事務來說 就等於沒做 獲取的都是之前的數據 但是 在A事務中查詢的話 查到的都是操作之後的數據 沒有提交的數據只有自己看得到,並沒有update到數據庫。 查看In

什麽是事務事務特性、事務隔離級別、spring事務傳播特性

ons pri table 產生 serializa support enc 不一致 修改 1.什麽是事務: 事務是程序中一系列嚴密的操作,所有操作執行必須成功完成,否則在每個操作所做的更改將會被撤銷,這也是事務的原子性(要麽成功,要麽失敗)。 2.事務特性: 事務特性分為

談談MySQL的事務隔離級別

提交 執行過程 操作 dnf 情況 以及 讀取 int 並且 這篇文章能夠闡述清楚跟數據庫相關的四個概念:事務、數據庫讀現象、隔離級別、鎖機制   一、事務 先來看下百度百科對數據庫事務的定義:   作為單個邏輯單元執行一系列操作,要麽完全執行,要麽完全不執行。事務處理可以

MySQL事務隔離級別的實現原理

存儲引擎 engine 講解 鎖定 官方文檔 ons tps 直接 一個 回顧 在MySQL的眾多存儲引擎中,只有InnoDB支持事務,所有這裏說的事務隔離級別指的是InnoDB下的事務隔離級別。 讀未提交:一個事務可以讀取到另一個事務未提交的修改。這會帶來臟讀、幻讀、不可

SQL Server 事務隔離級別

目前 lte log har 獲取 span 單用戶模式 最大 logs 參考文檔: https://docs.microsoft.com/zh-cn/sql/t-sql/statements/set-transaction-isolation-level-transact