認清SQL_Server_2005的基于行版本控制的兩種隔離級別

--認清SQL_Server_2005的基于行版本控制的兩種隔離級別
--By:zc_0101? Date:2010-03-31
--
快照隔離級別(snapshot)和已提交讀快照隔離級別(read?committed?snapshot)

--特點:在這兩種隔離級別下,讀取數據時不再請求共享鎖,而且永遠不會與修改進程的數據發生沖突,如果請求的
--
????????行被鎖定(例如正在被更新),SQL_Server會從行版本存儲區返回最早的關于該行的記錄(SQL_server會在
--
????????更新時將之前的行數據在tempdb庫中形成一個鏈接列表,當然目前我沒有搞清楚之前的數據到底存到了那里)
--
????????這兩個快照提供了樂觀的并發模型


--說明:首先這兩種隔離級別都是基于快照的實現模式,所以使用前必須修改數據庫選項"允許快照隔離"為ON,否則
--
????????以下兩種隔離級別將都被禁用:
????????ALTER?DATABASE?DBNAME?SET?ALLOW_SNAPSHOT_ISOLATION?ON
--????????修改這個選項時可能會需要將數據庫置為單用戶模式
????????ALTER?DATABASE?DBNAME?SET?SINGLE_USER?WITH?ROLLBACK?IMMEDIATE
--????????修改完允許快照隔離后再將數據庫重置為多用戶模式
????????ALTER?DATABASE?DBNAME?set?MULTI_USER
--????一、快照隔離級別是一種全新的隔離級別,在打開“允許快照隔離”選項后,不管是否使用快照隔離級別
????????SET?TRANSACTION?ISOLATION?LEVEL?SNAPSHOT?
--????????在更新數據時,SQL?SERVER總是會在tempdb庫中保存更改前的最后的行數據鏈接列表,從這里可以想到
--
????????將會影響SQL?SERVER在更新數據時的事務性能
--
????????當然,該隔離級別的主要作用是提高并發,所以在有讀取數據的地方時,請使用
????????SET?TRANSACTION?ISOLATION?LEVEL?SNAPSHOT?
--????二、已提交讀快照隔離級別,說得明白點,其實就是SQL?Server默認隔離級別已提交讀的衍生品,或者說是
--
????????另一種版本的已提交讀,或者是官方的說法:是已提交讀的新實現,官方的說法總是讓我們不能僅憑字面
--
????????意思就可以理解到本質。打開此數據庫選項的命令是:
????????ALTER?DATABASE?DBNAME?SET?read_committed_snapshot?ON
--????????在這里大家要明白,它只是一個數據庫選項開關,是在?READ?COMMITTED?隔離模式下時才會起作用,而且
--
????????將改變整個數據庫的全局行為。因為SQL?SERVER默認就是在READ?COMMITTED隔離模式下,所以在稍后的
--
????????示例中我們不會用到SET?TRANSACTION?ISOLATION?LEVEL?READ?COMMITTED語句,但是我們心里要明白。

--適用情況:主要是讀取數據的環境,在這種環境下偶爾需要修改操作并且很少發生更新沖突。

--區別:我們會在稍后的演示中進行說明,那樣更容易理解一些。


--示例一:快照
--
創建環境:
????IF?DB_ID('DB_TEST')?IS?NOT?NULL?DROP?DATABASE?DB_TEST;
????
GO
????
CREATE?DATABASE?DB_TEST
????
USE?DB_TEST;
????
GO
????
IF?OBJECT_ID('T_TEST','U')?IS?NOT?NULL?DROP?TABLE?T_TEST
????
GO
????
CREATE?TABLE?T_TEST(ID?INT?IDENTITY(1,1),COL?VARCHAR(50))
????
GO
????
INSERT?INTO?T_TEST?SELECT?'AAAAAAAAA'?UNION?ALL?SELECT?'BBBBBBBBBB'
????
GO
????
SELECT?*?FROM?T_TEST
????
/*
????????ID????COL
????????1????AAAAAAAAA
????????2????BBBBBBBBBB
????
*/
--????在連接1中執行如下語句(確保ALLOW_SNAPSHOT_ISOLATION已置為ON)
????USE?DB_TEST;
????
GO
????
ALTER?DATABASE?DB_TEST?SET?ALLOW_SNAPSHOT_ISOLATION?ON;
????
GO
????
BEGIN?TRAN
????????
SELECT?COL?FROM?T_TEST?WHERE?ID=2;
????????
UPDATE?T_TEST?SET?COL='CCCCCCC'?WHERE?ID=2;
????????
SELECT?COL?FROM?T_TEST?WHERE?ID=2;
--????通過輸出的結果我們可以看到,在未完成的事務中ID=2的COL值從'B'變為'C',而且你應該注意到我這里沒有使用
--
????快照隔離級別,還是用的SQL?SERVER默認隔離級別,但是因為我們打開了ALLOW_SNAPSHOT_ISOLATION選項,這
--
??個時候,我們的事務應該在更改ID=2的COL值之前就把之前的行狀態存儲到了tempdb中,那么我們怎么才能證明
--
????這個猜測呢,動態視圖sys.dm_tran_version_store可以幫助我們,執行:
????SELECT?*?FROM?sys.dm_tran_version_store
--????你一定可以看到在版本存儲區中已經有了一行數據了,接下來我們再打開一個連接2,執行如下SQL:
????USE?DB_TEST
????
GO
????
--SET?TRANSACTION?ISOLATION?LEVEL?SNAPSHOT;????--這里我們先注釋掉設置隔離級別為快照模式
????BEGIN?TRAN
????????
SELECT?COL?FROM?T_TEST?WHERE?ID=2;
--????可以看到查詢一直在等待,是因為我們在連接1中一直保持著該行的排它鎖X。但是現在我們把該事務commit或rollback
--
????掉,然后把快照隔離模式的注釋打開,重新執行上面的語句,我們就可以看到
????/*
????????BBBBBBBBBB
????
*/
--????我們可以想象到SQL?SERVER在這種隔離級別下的查找思路,它會先去原表查找該行數據,待發現該行被鎖后,則去
--
????tempdb數據庫存儲的行版本列表中取出最近的一次數據,這樣就避免了等待,但是前提是要求數據查詢不用那么精確
--
????的情況下,當然,你是否在這里忽略了一個問題,即:SQL?SERVER僅會在修改該行數據前才會去存儲最新的行版本,
--
????而在修改的事務結束后,SQL?SERVER并不會去更新之前的快照到最新的行版本,但是即使這樣我們也不用擔心,因為
--
????這個時候原表的該行數據已經不是鎖定狀態,其他之后的查詢依然會得到最新的數據。唯一注意的一點,我們還是用
--
????代碼說明:在連接1中用COMMIT?TRAN?提交事務,然后繼續執行連接2中的查詢:
????SELECT?COL?FROM?T_TEST?WHERE?ID=2;
--????我們發現數據還是之前的數據BBBBBBB,為什么?因為事務隔離級別!在事務中的任何地方讀取該行數據時,它獲取的
--
????總是在事務開始時獲取的數據,這里要牢記,因為他是稍后我們要說的已提交讀快照隔離級別的第一個不同點。


--????接下來我們說說快照隔離級別的另一個特點:沖突檢測,代碼說明,簡潔易懂:
--
????在連接1中執行如下語句:
????USE?DB_TEST;
????
GO
????
SET?TRANSACTION?ISOLATION?LEVEL?SNAPSHOT;--注意這里我們要設置隔離級別為快照模式
????BEGIN?TRAN
????????
SELECT?COL?FROM?T_TEST?WHERE?ID=2;
--????這里我們可以得到一個數據,然后再打開一個連接2,執行如下SQL:
????USE?DB_TEST;
????
GO
????
UPDATE?T_TEST?SET?COL='DDDDDDD'?WHERE?ID=2;
--????回到連接1,繼續執行SQL:
????UPDATE?T_TEST?SET?COL='EEEEEEE'?WHERE?ID=2;
--????這時SQL?SERVER?就會檢測到你在連接1中事務開始時讀取的數據已經與現在的數據發生了改變,所以就會報出更新
--
????沖突的錯誤:
????/*
????消息?3960,級別?16,狀態?4,第?1?行
????快照隔離事務由于更新沖突而中止。您無法在數據庫'DB_Test'中使用快照隔離來直接或間接訪問表?'dbo.T_TEST',
以便更新、刪除或插入已由其他事務修改或刪除的行。請重試該事務或更改?update/delete?語句的隔離級別。
????
*/
--????這里,其實就是快照隔離級別和已提交讀快照隔離級別的第二大區別了,READ?COMMITTED?SNAPSHOT不會檢測更新沖突


--示例二:已提交讀快照
--
????在連接1中執行如下語句:
????ALTER?DATABASE?DB_TEST?SET?READ_COMMITTED_SNAPSHOT?ON;--首先我們打開該數據庫選項(注意該選項需要
--
????上面提到的ALLOW_SNAPSHOT_ISOLATION選項的支持)
????USE?DB_TEST;
????
GO;
????
BEGIN?TRAN
????????
UPDATE?T_TEST?SET?COL='FFFFFFF'?WHERE?ID=2;
????????
SELECT?COL?FROM?T_TEST?WHERE?ID=2;
--????在該事務里,你將得到你剛剛更新過的值FFFFFFFF
--
????在連接2中執行如下語句:
????USE?DB_TEST;
????
GO
????
BEGIN?TRAN
????????
SELECT?COL?FROM?T_TEST?WHERE?ID=2;
--????這里你將得到連接1中的事務在修改數據之前的值,而非FFFFFF,這是肯定的。
--
????這時我們提交連接1中的事務:
????COMMIT?TRAN;
--????在連接2中再進行查詢時,我們驚奇的發現與在快照中不同的是,我們竟然在未完成的事務2中得到了連接1中的事務
--
????更改后的值!這也是為什么不會進行更新沖突檢測的原因,不如我們測試一下:
--
????將之前連接1中的事務提交或回滾,然后執行如下SQL:
????USE?DB_TEST;
????
GO
????
SET?TRANSACTION?ISOLATION?LEVEL?READ?COMMITTED;--這里我們顯示指定隔離級別是因為剛才指定的快照隔離
--
????????????????????????????????????????????????????級別會在沒有關閉的會話中一直有效。
????BEGIN?TRAN
????????
SELECT?COL?FROM?T_TEST?WHERE?ID=2;
--之后,我們再把連接2中的事務提交或回滾掉,執行如下SQL:
????SET?TRANSACTION?ISOLATION?LEVEL?READ?COMMITTED;
????
UPDATE?T_TEST?SET?COL='aaaaa'?WHERE?ID=2;
????
SELECT?COL?FROM?T_TEST?WHERE?ID=2;
--????好了,這個時候我們再在連接1中更新這條在事務1中讀取后但是在外部被更新過的數據:
????UPDATE?T_TEST?SET?COL='測試已提交讀更新沖突檢測'?WHERE?ID=2;
--????我們發現更新可以正常進行,最后我們關閉所有連接,并更改數據庫選項:
????ALTER?DATABASE?DB_TEST?SET?ALLOW_SNAPSHOT_ISOLATION?OFF;
????
ALTER?DATABASE?DB_TEST?SET?READ_COMMITTED_SNAPSHOT?OFF;

--總結:快照隔離模式是樂觀并發模型,可以避免臟讀、丟失更新、不可重復讀、幻讀、而且有更新沖突檢測的特點。
--
???????已提交快照讀隔離模式和已提交讀模式是相同的,都是只能避免臟讀,都無更新沖突檢測,但是不同的是,已
--
????????提交讀快照隔離級別是樂觀并發模型,并且讀取數據不會發生等待。
--
另附所有隔離級別的允許或防止的問題等。
==============================================================================================
隔離級別????????臟讀????????丟失更新????????不可重復讀????幻讀????????并發模型????????更新沖突檢測
----------------------------------------------------------------------------------------------
未提交讀????????是????????????是????????????是????????是????????悲觀????????????????否
----------------------------------------------------------------------------------------------
已提交讀?????  否????????????是????????????是????????是???????悲觀????????????????否
----------------------------------------------------------------------------------------------
可重復讀????????否????????????否????????????否????????是????????悲觀????????????????否
----------------------------------------------------------------------------------------------
可串行讀????????否????????????否????????????否????????否????????悲觀????????????????否
----------------------------------------------------------------------------------------------
快照????????????否????????????否????????????否????????否????????樂觀????????????????是
----------------------------------------------------------------------------------------------
已提交讀快照????否????????????是????????????是????????是????????樂觀????????????????否
==============================================================================================

轉載于:https://www.cnblogs.com/qanholas/archive/2012/01/04/2312324.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/380011.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/380011.shtml
英文地址,請注明出處:http://en.pswp.cn/news/380011.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java SecurityManager checkPermission()方法與示例

Syntax: 句法: public void checkPermission(Permission perm);public void checkPermission(Permission perm, Object cntxt);SecurityManager類的checkPermission()方法 (SecurityManager Class checkPermission() method) checkPermission() method is availa…

匯編test指令

功能:將兩個操作數進行邏輯與運算,并根據運算結果設置相關的標志位,并不改變操作數1和操作數2的值 test 操作數1,操作數2我們經常用test來判斷一個值是否為0,用法: test 操作數1,操作數1比如我…

CSS兼容IE/Firefox要點

首先我們說說firefox和IE對CSS的寬度顯示有什么不同: 其實CSS ’width’ 指的是標準CSS中所指的width的寬度,在firefox中的寬度就是這個寬度。它只包含容器中內容的寬度。而Internet Explorer ’width’則是指整個容器的寬度,包括內容&#x…

Java GregorianCalendar computeFields()方法與示例

GregorianCalendar類computeFields()方法 (GregorianCalendar Class computeFields() method) computeFields() method is available in java.util package. 在java.util包中提供了validateFields()方法 。 computeFields() method is used to compute the calendar fields and…

JS、JNS、JP(JPE)、JNP(JPO)指令詳解、從原理上解釋

JS 格式: js 地址當執行到JS指令時,如果標志位SF1,則跳轉到指定的地址,如果SF0,不跳轉 比如: cmp eax,ecx js 0040100c此時eax0,ecx1,執行完cmp命令,符號標…

zz如何保持專心

養成好習慣 養成在固定時間、固定地點專心學習工作的好習慣。 如果可能,在進入學習或者工作狀態前做一些小儀式,比如擺個姿勢,戴上學習帽什么的。就好像在運動前做準備活動一樣,給身體一個提示。讓頭腦做好準備 避免在學習前做什么…

Java——File類

一,File類的概述和構造方法 A:file類的概述 file類可以理解成一個路徑 文件夾或者是文件夾路徑 路徑分為絕對路徑和相對路徑 絕對路徑是一個固定的路徑,從盤符開始 這里的G:\TIM 就是一個絕對路徑,是一個固定的路…

Linux進程環境

一 main函數 當內核使用一個exec函數執行C程序時,在調用main函數之前先調用一個特殊的啟動例程,可執行程序將此例程指定為程序的起始地址。啟動例程從內核獲取命令行參數和環境變量,然后為調用main函數做好準備。 二 進程終止 進程終止的方式…

JO、JNO、JB、JNB命令詳解(從原理上)

JO 當執行到jo命令時,如果ZF標志位為1,則跳轉,反之不跳轉 add eax,ecx jo 00401000c此時eax7fff ffff ,ecx0000 0001,執行完add命令,OF1,原因是eax存儲的最大值是7fffffff,再加1&a…

java 根據類名示例化類_Java類類getProtectionDomain()方法及示例

java 根據類名示例化類類class getProtectionDomain()方法 (Class class getProtectionDomain() method) getProtectionDomain() method is available in java.lang package. getProtectionDomain()方法在java.lang包中可用。 getProtectionDomain() method is used to return …

snagit 9.0注冊碼

8.0的注冊碼 A5CCU-RYNM4-C9ECC-5CWW9-B5R7B 5HCC5-4CCC9-NGXCM-XYDZ5-H6ER6 HLHAD-2CZLC-8XYDC-CC5CB-P289A D5DSC-WZCBM-JRHSC-QVTEV-TR7R8 snagit 9.0: name:Team Z.W.T sn:XMYU5-9CMBC-5SLBZ-DKML2-JE8M5 謝謝 name:Team Z.W.T sn: WDYMP-8ALRM-GVVV2-PH8VK-6MD27 Z…

vue3 配置 @符號

config,ts 配置 有 爆紅 安裝 npm install 一下 然后 配置 路徑提示功能 tsconfig.json 配置 路徑提示功能 一共這兩個路徑配置

android 頁面轉換

通過setContentView來改變布局 很簡單 ViewchangeActivity.java package idrc.change;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class ViewchangeActivity extends Activity {/** Called when the…

mts模式_MTS的完整形式是什么?

mts模式MTS:Microsoft Transaction Server /移動電話服務/多通道電視聲音 (MTS: Microsoft Transaction Server/ Mobile Telephone Service/ Multichannel Television Sound) 1)MTS:Microsoft Transaction Server (1) MTS: Microsoft Transaction Server…

Java——IO流

一,IO流常識 Ⅰ,IO流的概述 1,IO流用來處理設備之間的數據傳輸 2,Java對數據的操作都是通過流的方式 3,Java用于操作流的類都在IO包中 4,流 按流向分為: ①輸入流 ②輸出流 5&#xff0…

JBE、JNBE、JA、JL指令詳解(從原理上)

JBE 當執行到JBE命令時,如果此時的CF標志位或者ZF標志位為1,跳轉,其他不跳轉 相當于小于等于命令 cmp eax,ecx jbe 0040100c執行到cmp命令時,如果此時的eac小于等于ecx,jbe都會跳轉到0040100c 因為小于的…

數組shift方法_數組shift()方法以及JavaScript中的示例

數組shift方法JavaScript shift()方法 (JavaScript shift() method) shift() method is used to remove the first element of an array and returns the deleted element. shift()方法用于刪除數組的第一個元素,并返回刪除的元素。 It changes the array length. …

ArcMap 9使用技巧

ArcMap 9使用技巧技巧1 重疊要素的選擇切換目標:在覆蓋同一區域的多個要素中切換被選擇要素操作步驟:1.在編輯環境中選中覆蓋同一區域的多個要素中的一個要素2.按下N 鍵,被選要素就會自動地切換到另一個圖層的要素3&am…

《軟件》2011年第6期刊登出 《DB 查詢分析器》中斷SQL語句的執行

《軟件》編輯部寄來了2011年第6期樣刊,在2011年第6期,刊登出了本人的論文------“《DB 查詢分析器》中斷SQL語句的執行”。 論文刊登在第42頁,排在第13篇,還比較靠前,呵呵。 在“萬方數據”和“中國期刊全文數據庫”中…

Java——IO流(序列流)

序列化與反序列化 游戲存檔:目的是為了游戲下次上號數據的保存 package com.yy.otherio;import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; im…