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

sqlserver 事務隔離級別

SQL Server通過在鎖資源上使用不同型別的鎖來隔離事務。為了開發安全的事務,定義事務內容以及應在何種情況下回滾至關重要,定義如何以及在多長時間內在事務中保持鎖定也同等重要。這由隔離級別決定。應用不同的隔離級別,SQL Server賦予開發者一種能力,讓他們為每一個單獨事務定義與其他事務的隔離程度。事務隔離級別的定義如下:
  • 是否在讀資料的時候使用鎖
  • 讀鎖持續多長時間
  • 在讀資料的時候使用何種型別的鎖
  • 讀操作希望讀已經被其他事務排他鎖住的資料時,怎麼辦?在這種情況下,SQL Server可以:
    • 一直等到其他事務釋放鎖
    • 讀沒有提交的資料
    • 讀資料最後提交後的版本
ANSI 99定義了4種事務隔離級別,SQL Server 2005
能夠完全支援這些級別:
  • 未提交讀 在讀資料時不會檢查或使用任何鎖。因此,在這種隔離級別中可能讀取到沒有提交的資料。
  • 已提交讀 只讀取提交的資料並等待其他事務釋放排他鎖。讀資料的共享鎖在讀操作完成後立即釋放。已提交讀是SQL Server的預設隔離級別。
  • 可重複讀 像已提交讀級別那樣讀資料,但會保持共享鎖直到事務結束。
  • 可序列化 工作方式類似於可重複讀。但它不僅會鎖定受影響的資料,還會鎖定這個範圍。這就阻止了新資料插入查詢所涉及的範圍,這種情況可以導致幻像讀。
此外,SQL Server還有兩種使用行版本控制來讀取資料的事務級別(本章後文將詳細檢驗這些隔離級別)。行版本控制允許一個事務在資料排他鎖定後讀取資料的最後提交版本。由於不必等待到鎖釋放就可進行讀操作,因此查詢效能得以大大增強。這兩種隔離級別如下:
  • 已提交讀快照 它是一種提交讀級別的新實現。不像一般的提交讀級別,SQL Server會讀取最後提交的版本並因此不必在進行讀操作時等待直到鎖被釋放。這個級別可以替代提交讀級別。
  • 快照 這種隔離使用行版本來提供事務級別的讀取一致性。這意味著在一個事務中,由於讀一致性可以通過行版本控制實現,因此同樣的資料總是可以像在可序列化級別上一樣被讀取而不必為防止來自其他事務的更改而被鎖定。
無論定義什麼隔離級別,對資料的更改總是通過排他鎖來鎖定並直到事務結束時才釋放。很多情況下,定義正確的隔離級別並不是一個簡單的決定。作為一種通用的規則,要選擇在儘可能短的時間內鎖住最少資料,但同時依然可以為事務提供它所需的安全程度的隔離級別

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED  --未提交讀
SET TRANSACTION ISOLATION LEVEL READ COMMITTED    --已提交讀
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ   --獲取一致的可重複讀操作 
SET TRANSACTION ISOLATION LEVEL SNAPSHOT          --已提交讀快照級
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE      --系列化級別

(一)、引數SNAPSHOT的含義:1.指定事務中任何語句讀取的資料都將是在事務開始時便存在的資料的事務上一致的版本。事務只能識別在其開始之前提交的資料修改。在當前事務中執行的語句將看不到在當前事務開始以後由其他事務所做的資料修改。其效果就好像事務中的語句獲得了已提交資料的快照,因為該資料在事務開始時就存在。2.除非正在恢復資料庫,否則 SNAPSHOT事務不會在讀取資料時請求鎖。讀取資料的 SNAPSHOT事務不會阻止其他事務寫入資料。寫入資料的事務也不會阻止 SNAPSHOT事務讀取資料。3.在資料庫恢復的回滾階段,如果嘗試讀取由其他正在回滾的事務鎖定的資料,則 SNAPSHOT事務將請求一個鎖。在事務完成回滾之前,SNAPSHOT事務會一直被阻塞。當事務取得授權之後,便會立即釋放鎖。4.必須將 ALLOW_SNAPSHOT_ISOLATION資料庫選項設定為 ON,才能開始一個使用 SNAPSHOT隔離級別的事務。如果使用 SNAPSHOT隔離級別的事務訪問多個數據庫中的資料,則必須在每個資料庫中將 ALLOW_SNAPSHOT_ISOLATION都設定為 ON5.不能將通過其他隔離級別開始的事務設定為 SNAPSHOT隔離級別,否則將導致事務中止。如果一個事務在SNAPSHOT隔離級別開始,則可以將它更改為另一個隔離級別,然後再返回 SNAPSHOT。一個事務從執行 BEGIN TRANSACTION 語句開始。6. SNAPSHOT隔離級別下執行的事務可以檢視由該事務所做的更改。例如,如果事務對錶執行 UPDATE,然後對同一個表發出 SELECT 語句,則修改後的資料將包含在結果集中。

 (二)、引數REPEATABLE READ的含義:

1.指定語句不能讀取已由其他事務修改但尚未提交的行,並且指定,其他任何事務都不能在當前事務完成之前修改由當前事務讀取的資料。2.對事務中的每個語句所讀取的全部資料都設定了共享鎖,並且該共享鎖一直保持到事務完成為止。這樣可以防止其他事務修改當前事務讀取的任何行。其他事務可以插入與當前事務所發出語句的搜尋條件相匹配的新行。如果當前事務隨後重試執行該語句,它會檢索新行,從而產生幻讀。由於共享鎖一直保持到事務結束,而不是在每個語句結束時釋放,所以併發級別低於預設的 READ COMMITTED 隔離級別。此選項只在必要時使用。

(三) 、READ UNCOMMITTED

指定語句可以讀取已由其他事務修改但尚未提交的行。 READ UNCOMMITTED級別執行的事務,不會發出共享鎖來防止其他事務修改當前事務讀取的資料。READ UNCOMMITTED事務也不會被排他鎖阻塞,排他鎖會禁止當前事務讀取其他事務已修改但尚未提交的行。設定此選項之後,可以讀取未提交的修改,這種讀取稱為髒讀。在事務結束之前,可以更改資料中的值,行也可以出現在資料集中或從資料集中消失。該選項的作用與在事務內所有 SELECT語句中的所有表上設定 NOLOCK相同。這是隔離級別中限制最少的級別。 SQL Server 2005中,您還可以使用下列任意一種方法,在保護事務不髒讀未提交的資料修改的同時儘量減少鎖定爭用:1.READ COMMITTED隔離級別,並將 READ_COMMITTED_SNAPSHOT資料庫選項設定為 ON2.SNAPSHOT隔離級別。

(四)、READ COMMITTED

指定語句不能讀取已由其他事務修改但尚未提交的資料。這樣可以避免髒讀。其他事務可以在當前事務的各個語句之間更改資料,從而產生不可重複讀取和幻像資料。該選項是 SQL Server的預設設定。READ COMMITTED 的行為取決於 READ_COMMITTED_SNAPSHOT資料庫選項的設定:1.如果將 READ_COMMITTED_SNAPSHOT設定為 OFF(預設設定),則資料庫引擎會使用共享鎖防止其他事務在當前事務執行讀取操作期間修改行。共享鎖還會阻止語句在其他事務完成之前讀取由這些事務修改的行。語句完成後便會釋放共享鎖。2.如果將 READ_COMMITTED_SNAPSHOT設定為 ON,則資料庫引擎會使用行版本控制為每個語句提供一個在事務上一致的資料快照,因為該資料在語句開始時就存在。不使用鎖來防止其他事務更新資料。 READ_COMMITTED_SNAPSHOT資料庫選項設定為 ON時,您可以使用 READCOMMITTEDLOCK表提示為 READ_COMMITTED隔離級別上執行的事務中的各語句請求共享鎖,而不是行版本控制。注意:設定 READ_COMMITTED_SNAPSHOT選項時,資料庫中僅允許存在執行 ALTER DATABASE命令的連線。在 ALTER DATABASE完成之前,資料庫中不允許有其他開啟的連線。資料庫不必處於單使用者模式。

(五)、SERIALIZABLE

請指定下列內容:1.語句不能讀取已由其他事務修改但尚未提交的資料。2.任何其他事務都不能在當前事務完成之前修改由當前事務讀取的資料。3.在當前事務完成之前,其他事務不能使用當前事務中任何語句讀取的鍵值插入新行。範圍鎖處於與事務中執行的每個語句的搜尋條件相匹配的鍵值範圍之內。這樣可以阻止其他事務更新或插入任何行,從而限定當前事務所執行的任何語句。這意味著如果再次執行事務中的任何語句,則這些語句便會讀取同一組行。在事務完成之前將一直保持範圍鎖。這是限制最多的隔離級別,因為它鎖定了鍵的整個範圍,並在事務完成之前一直保持範圍鎖。因為併發級別較低,所以應只在必要時才使用該選項。該選項的作用與在事務內所有 SELECT 語句中的所有表上設定 HOLDLOCK相同。需要注意的地方:1.一次只能設定一個隔離級別選項,而且設定的選項將一直對那個連線始終有效,直到顯式更改該選項為止。事務中執行的所有讀取操作都會在指定的隔離級別的規則下執行,除非語句的 FROM 子句中的表提示為表指定了其他鎖定行為或版本控制行為。2.事務隔離級別定義了可為讀取操作獲取的鎖型別。針對 READ COMMITTED  REPEATABLE READ 獲取的共享鎖通常為行鎖,儘管當讀取引用了頁或表中大量的行時,行鎖可以升級為頁鎖或表鎖。如果某行在被讀取之後由事務進行了修改,則該事務會獲取一個用於保護該行的排他鎖,並且該排他鎖在事務完成之前將一直保持。例如,如果 REPEATABLE READ 事務具有用於某行的共享鎖,並且該事務隨後修改了該行,則共享行鎖便會轉換為排他行鎖。3.在事務進行期間,可以隨時將事務從一個隔離級別切換到另一個隔離級別,但有一種情況例外。即在從任一隔離級別更改到 SNAPSHOT 隔離時,不能進行上述操作。否則會導致事務失敗並回滾。但是,可以將在 SNAPSHOT 隔離中啟動的事務更改為任何其他隔離級別。4.將事務從一個隔離級別更改為另一個隔離級別之後,便會根據新級別的規則對更改後讀取的資源執行保護。在更改前讀取的資源將繼續按照以前級別的規則受到保護。例如,如果某個事務從 READ COMMITTED 更改為SERIALIZABLE,則在該事務結束前,更改後所獲取的共享鎖將一直處於保留狀態。5.如果在儲存過程或觸發器中發出 SET TRANSACTION ISOLATION LEVEL,則當物件返回控制時,隔離級別會重設為在呼叫物件時有效的級別。例如,如果在批處理中設定 REPEATABLE READ,並且該批處理呼叫一個將隔離級別設定為 SERIALIZABLE 的儲存過程,則當該儲存過程將控制返回給該批處理時,隔離級別就會恢復為 REPEATABLE READ