1. 程式人生 > >事務與鎖定

事務與鎖定

一、併發及併發控制模型

    在資料庫併發就是多個程序同時取、存資料庫裡資料的能力。著眼我們開發的系統,當然是激動態的並互不打架的併發使用者程序越多併發能力就越強大啦,你想想看好多的網上購物系統,如果沒有併發處理的能力,那麼在上面登記的使用者資訊、商品有庫存資訊及使用者帳戶資訊很難保證正確性和一致性,比如一個物品本身庫存只有100個,結果如果100人同時線上進行預定,庫存就有可能搞一個100-1的效果出來。

    很顯然對上述的例子我們希望一個程序在修改庫存資料時必須阻止其它程序讀或修改資料,或是正在讀的使用者程序限制其它活動的使用者程序進行讀或修改的操作,這樣一來勢必造成系統的併發效能下降,但是如果不採用這種辦法又無法保證資料正確性和一致性。那怎麼解決這個問題呢,辦法只有通過不同的併發模式來管理這些併發事件。我們下面來理解併發控制的模式、併發下可能發生的非一致資料行為,即併發副作用,並由模式及資料行為引入事務及相關的5個隔離等級等概念,進而來理解不同隔離等級下併發實現的機理,顯然我們自己也就可以回答上面這個問題了。

併發控制模式:一般併發控制模式有兩種:積極併發(又稱樂觀併發)和消極併發(又稱悲觀併發)。積極併發是SQL2005才引入的新模式,在2005以前的版本其實只有唯一的併發模式即:消極併發。那什麼是消極併發呢?消極併發就是SQLSERVER預設行為是程序以獲取鎖的方式來阻止其它程序對正在使用的資料進行修改的能力。對於資料庫來說對資料修改的操作程序肯定很多,這些程序肯定都會去影響其它程序讀取資料的能力,反之,對資料進行讀時加上鎖也一定會影響其它程序修改資料的能力,簡而言之,就是讀取與修改資料之間是衝突的、互相阻塞的。樂觀併發是SQL2005利用一個行版本控制器的新技術來處理上述的衝突。行版本控制器在當前程序讀取資料時生成舊版本的資料,使得其它請求讀的程序能看到當前程序一開始讀取時的資料狀態,並且不受當前程序或其它程序對資料進行修改的影響。簡而言之讀與修改之間是不衝突的,但是修改與修改之間還是衝突的。

    對於這兩種併發模式兩個程序同時請求資料修改必然會衝突的,除此以外的差別在於一個是在衝突發生前進行控制,另一個在衝突發生了進行協調處理。這好比生活一樣,兩種方式就是兩種不同的人生,一種消極怠工一種積極向上。

二、併發下可能發生的併發副作用:丟失更新、髒讀、不可重複讀、幻影。

    為了把這些可能發生的併發副作用說清楚,我們先“佈置”一個場景:這是一個賣工藝石頭的小商店,平時在前場完成交易,客戶憑單據到後場領取石頭,AMM和BMM是營業員,她們平時掌握庫存數是通過大廳裡的一塊LED顯示牌得之,並且在各自完成一筆交易後修改LED顯示,以保證資料的實時性。在這個場景下我們來觀察可能發生的行為:

1、  丟失更新:

丟失更新估計是所有資料庫使用者都不想發生的情況,什麼是丟失更新呢?丟失更新是當2個或兩個以上的使用者程序同時讀取同樣的資料後又企圖修改原來的資料時就會發生。好在上述場景下,大廳LED顯示牌顯示當前庫存1000,這時同時有兩個客戶上門了,AMM和BMM滿面春風接待,比如AMM賣出1個,BMM呢賣出了10個,AMM處理完業務後趕緊把LED顯示數修改為1000 - 1 = 999個,幾乎同一時間BMM處理完自己的業務後習慣性的把LED顯示數修改為1000 - 10 = 990 個,這時老闆從後場過來,看著LED有點不爽,大吼一聲:現在還有多少存貨呀?,AMM說我賣了1個,BMM說我是10個,不過兩個人都傻眼了,LED顯示怎麼是990呢?原來BMM在更改時把AMM做的更改搞丟了,這就是丟失更新。顯然對老闆和營業員來說都是必須迴避不能發生的事。

2、  髒讀

很顯然,在上面的例子裡因為AMM和BMM事先因為不知道對方已經修改了櫃檯存貨,所以才造成了存貨數目顯示錯誤,出了問題我們要想辦法解決問題,英明的老闆說了,你們隨便哪個在談一筆生意時先把客戶意向購賣石頭數扣掉,如果最後客戶不要你再改回頭,兩個MM對老闆的英明決定表示等贊同,可是問題還是發生了,怎麼回事呢,還是假設櫃臺存貨1000個石頭,AMM有一筆生意正在談著,顧客意向要600塊石頭,AMM趕緊把LED顯示修改為400。這時BMM也很興奮因為她已經談成一筆700塊石頭的生意,所以呢BMM擡頭一看,好嘛,還有400塊可賣,完了BMM的生意做不成了,只好向客戶表達歉意。BMM只能讓老闆進貨,可是老闆一看LED顯示還有1000塊怎麼你的700塊生意做不成了呢?哦,因為最後AMM的600塊生意沒做成。嘿嘿,也就是BMM錯誤的讀取了AMM修改的資料,完成了一次“髒讀”操作。髒讀也就是一個使用者程序讀取了另一個使用者程序修改過但沒有正式提交的資料,這時導致了資料不一樣的情形發生了。因為A使用者程序是無法確認另一個B使用者程序在自己提交資料前是否修改過資料,這是資料庫系統預設情況下必須迴避的。

3、  不可重複讀

不可重複讀又稱不一致分析,不過,個人以為似乎不一致分析更讓人好理解一點,但是大部分地方稱不可重複讀。不可重複讀是指一個使用者程序兩次讀取資料得到不同樣的資料。比如那個英明的老闆吧,他知道要盤點,掌握庫存的變化,忙得満頭大汗,終於計出庫存數來,比如說1000吧,或是當他跑到大廳一看LED顯示牌卻只有了900,顯然這一次的檢查庫存的過程中兩次得到庫存數不一樣,原因就是AMM在老闆從後場走到前場的過程中做了一擔生意,賣出100塊。嘿嘿,老闆氣又不是不氣又不是,這AMM真可愛,做生意挺兩下呀!顯然在一個使用者程序兩次讀取資料間隔內另一個使用者程序修改了資料,這就是不可重複讀。

4、  幻影

幻影,嘿嘿,我們不是經常無視BS自己的人嗎?你無視他並不代表他不BS你吧,這個BS你的人就成了幻影,嘿嘿開個玩笑。這種情況多數在查詢帶謂詞時結果集內部分資料變化的時候發生,如果謂詞限定下在一個交易裡兩次同一查詢的結果集不同,那些不同的行或行集就是幻影。比方說英明的老闆到大廳走走,順便請大家吃飯,數數人數,BMM,。。。。一路數過去,發現有10人,呵呵,正好一桌,,通知好她們後老闆回辦會室拿人民幣,回到前場看見AMM,再一數11人,暈,剛才怎麼看到AMM ?AMM也知道了老闆請客沒數到他,很是生氣,這時AMM就成了幻影。

以上是四種併發副作用只是一個交易事務裡或事務間可能發生的異常的非一致的資料行為(記好併發副作用和不一致的資料行為術語,這在以後會經常提及),其實還是有好多的行為是我們所期望的,那麼我們期望的行為是什麼呢,下面我們在事務裡來介紹。我們可以通過隔離級別來設定一個合適級別以決定上述上種資料行為哪些是允許的。那什麼是交易事務,什麼又是隔離等級呢?

三、事務

    事務是資料庫一筆交易的基本單元,存於兩種併發模型中。又分為顯式事務和隱式事務。顯式事務是顯式的開始一個事務並顯式的滾回或提交事務,除了顯式的事務還有隱式的了,隱式事務是資料庫自己根據情況完成的事務處理,如單獨的select、update、delete、select語句。

    作為一個事務,它能保證資料庫的資料一致性及重做。提到事務不得不提及事務的ACID屬性:原子性、一致性、隔離性及永續性。不管是顯式還是隱式的,都必須維持這四個屬性。

    原子性:一個事務是一個整體,要不全部提交,要不全部中止。意思就是要不全部成功提交到資料,要不全部回滾恢復事務開始前的狀態。比方我們做一個入庫操作,在這個事務裡,稽核入庫單和修改庫存作為一個整體,要不單據變成稽核過同時庫存增加相應的值,要不就是單據未稽核同時庫存不變。

    一致性:一致性要求事務保證資料在邏輯上正確,處理的結果不是一個不確定的狀態,什麼是不確定狀態呢,比如說我們完成一個庫存減少的操作,如果沒有一個出貨單據那麼這個庫存的當前修改就是一個不確定狀態,因為你無法知道減少的東東到哪兒去了。

    隔離性:這個隔離和鎖定有關,以後在說鎖的過程中會提到這些,你先記住這個就行。

永續性:持久很顯然是要求正確提交的修改必須保證長久存在,不會因為關機或掉電把這筆交易丟掉。進行中的事務發生故障那事務就完全撤銷,像沒有發生一樣,如果事務提交的確認已經反饋給應用程式發生故障,那麼這些日誌利用先寫技術,在啟動恢復階段自動完成相應的動作保證事務的永續性。(這個在前面的引擎元件有過介紹哦。)

四、隔離等級

    首先來說說隔離,隔離是一個事務必須與其他事務所進行的資源或資料更改相隔開,顯然隔離等級就是相隔的程度了吧。在說隔離級別不得不提及鎖的概念,但是在本單不提及鎖,在以後聽章節裡再作說明,大家只要有個印象就行。在這兒我們必須明白兩件事:

    1,隔離級別不會影響程序獲得資料修改的排它鎖,並且這個鎖會儲存到事務結束。相對於讀程序來說,隔離級別就是對讀操作的一個保護級別,保護讀操作受其它事務影響的程式。

    2,較低的隔離級別可以增強許多使用者同時訪問資料的能力,但也增加了使用者可能遇到的併發副作用(例如髒讀或丟失更新)的數量。相反,較高的隔離級別減少了使用者可能遇到的併發副作用,卻需要太多的系統資源及一個事務阻塞其他事務的可能性。

    應平衡應用程式的完整性要求與相應隔離級別的系統開銷,在此基礎上選擇相應的隔離級別。最高隔離級別(可序列化)保證事務在每次重複讀取操作時都能準確檢索到相同的資料,但需要通過執行某種級別的鎖定來完成此操作,而鎖定可能會影響其他使用者程序。最低隔離級別(未提交讀)可以檢索其他事務已經修改但未提交的資料。在未提交讀中,所有併發副作用都可能發生,但因為沒有讀鎖定或修改阻塞讀取,所以開銷最少。

    不同的隔離級別決定我們有哪些資料副作用可以發生,而併發模型決定不同隔離等級下如何來限制這些資料行為或如何協調這資料行為。好,那我們來關注一下不同隔離等級下如何限制這些行為的發生。

    未提交讀(uncommitted Read):字面理解一下,修改了的未提交資料可以讀取。準確點:一個使用者程序可以讀取另一個使用者程序修改卻未提交的資料。SQL SERVER對這個等級下的讀操作不需要獲得任何鎖就可以讀取資料,因為不需要鎖所以不會和其它任何程序互相阻塞,自然而然能讀取其它程序修改了的卻未提交資料。顯然這不是我們理想的一種模式,但是它卻有了高併發性,因為讀操作沒有鎖不會影響其它程序的讀或寫操作。在這種級別下,除了丟失更新(上一講中的資料可能發生的行為)外,其它行為都有可能發生,冒著資料不一致的風險來避免修改的程序阻塞讀取的程序,事務的一致性肯定是得不到保障,顯然這是消極併發模式下的迴避阻塞頻繁的一種解決方案。未提交讀那肯定是不適合於股票、金融系統的,但是在一些趨勢分析的系統裡,要求的只是一種走向,準確性可以不是那麼嚴格時,這個級別因併發效能超強成為首選。

    已提交讀(Read Committed):它和未提交讀相反,已提交讀級別保證一個程序不可能讀到另一個程序修改但未提交的資料。這個級別是引擎預設的級別,也是2005樂觀併發模式下支援的級別,也就是說已提交讀可是樂觀的也可以是悲觀的,那究竟當前庫是屬於哪個併發模型下的已提交讀呢,這取決於一個READ_COMMITED_SNAPSHOT資料庫配置項,並且預設是悲觀併發控制的。這個配置項決定已提交讀級別下事務使用鎖定還是行版本控制,並很顯然行版本控制是樂觀併發模式,鎖定是悲觀併發模式。我們來點角本看看:

--設定已提交讀隔離使用行版本控制

ALTER DATABASE testcsdn SET READ_COMMITTED_SNAPSHOT ON

GO

--檢視當前已提交讀隔離併發模型

select name,database_id,is_read_committed_snapshot_on  from sys.databases

/*

  name                  database_id is_read_committed_snapshot_on

--------------------   ----------- -----------------------------

master                       1           0

tempdb                       2           0

model                        3           0

msdb                         4           0

ReportServer$SQL2005         5           0

ReportServer$SQL2005TempDB   6           0

TestCsdn                     7           1  --current

(7 行受影響)

*/

--設定已提交讀隔離使用鎖定

ALTER DATABASE testcsdn SET READ_COMMITTED_SNAPSHOT OFF

GO

--檢視已提交讀隔離併發模型

select name,database_id,is_read_committed_snapshot_on  from sys.databases

/*

  name                  database_id is_read_committed_snapshot_on

--------------------   ----------- -----------------------------

master                       1           0

tempdb                       2           0

model                        3           0

msdb                         4           0

ReportServer$SQL2005         5           0

ReportServer$SQL2005TempDB   6           0

TestCsdn                     7           0 --curret

(7 行受影響)

*/

    已提交讀在邏輯上保證了不會讀到不實際存在的資料。悲觀併發下的已提交讀,當程序要修改資料時會在資料行上申請排它鎖,其它程序(無論是讀還是寫)必須等到排它鎖釋放才可以使用這些資料。如果程序僅是讀取資料時會使用共享鎖,其它程序雖然可以讀取資料但是無法更新資料,必須等到共離鎖釋放(共享鎖在資料處理完即釋放,比如行共享鎖在當前資料行資料處理完就自動釋放,不會在整個事務內保留髮。)。樂觀併發的已提交讀,也確保不會讀到未提交的資料,不是通過鎖定的方式來實現,而是通過行版本控制器生成行的提前交的資料版本,被修改的資料雖然仍然鎖定,但是其它程序可以可以讀取更新前版本資料。

    可重複讀(Repeatable Read):這也是一個悲觀併發的級別。可重複讀比已提交讀要求更嚴格,在已提交讀的基礎上增加了一個限制:獲取的共享鎖保留到事務結束。在這個限制下,程序在一個事務裡兩交次讀取的資料一致,也就是不會讀取到其它程序修改了資料。在這兒我們提到共享鎖會保留到事務結束,那得申明一下無論哪種級別及併發模型,排它鎖是一定要保留到事務結束的。在可重複讀級別共享鎖同樣也會保留到事務結束。那麼這種對資料安全的保證是通過增加共享保留的開銷為代價的,也就是隻要開始一個事務,其它使用者程序是不可能修改資料的,顯而易見的系統的併發性和效能必然下降。這似乎是我們想像中的一種級別,雖然這個級別暫時無法迴避幻影讀,而且我們也默許併發及效能下降,那只有對程式設計師對事務的控制有嚴格的要求:事務要短並儘量不要人為因素的干擾,減少潛在的鎖競爭。

    快照(SnapShot):樂觀併發級別。這是2005新增加的一個隔離級別。快照級別與使用樂觀併發的已提交讀差不多,差別在於行版控制器裡的資料版本有多早,這個在以後講鎖時再說。這個級別保證了一個事務讀取的資料是事務開始時就在資料庫邏輯上確認並符合一致性的資料。讀操作不會要求共享鎖定,如果要求的資料已經排它,就會通過行版本控制器讀取最近的符合一致性的資料。

    可序列化:是目前最嚴謹、最健壯的一個級別,屬於悲觀併發。它防止幻影的發生,迴避了以前所有意外行為的發生。可序列化意味著系統按程序進入佇列的順序依次、序列化的執行的結果與事務同時執行得到一致的結果。這個最健壯的級別顯然共享鎖也是隨事務開始隨事務結束,並通過鎖定部分不存在的資料(即索引鍵範圍鎖定)來回避幻影的發生。

        在前面的兩篇裡我從純理論上把事務相關的知識作了一個梳理,有人看了一定覺得無味了吧,好這一篇我們加入一點T-SQL語句把前面所說有東東關聯起來,我們人為產生鎖定來理解不同的意外資料行為在不同隔離等級下的表現,順便再重溫一下意外資料行及隔離等級,讓大家對交易事務有一個直觀的認識。

     在進行例項前不得不先介紹一點鎖的知識,注意這兒只是簡單的說一下,不作深入討論。我們根據使用者訪問資源的行為先歸納出幾種鎖,這幾種鎖在下面的例項裡會出現,它們為:共享鎖定、排它鎖定、更新鎖定及用意向這個限定詞限定的三種鎖(意向共享、意向排它、意向更新),噹噹然還有其它的模式,我們在下一篇再說。意向鎖的存在是解決死鎖的發生,保證程序在申請鎖定前確定當前資料是否存在不相容性的鎖定。

    先對上面提到的鎖作一個簡單的描述,更詳細的下面再說。

   共享鎖定發生在查詢記錄時,直觀就是我們select啦,但是並不是只有select才有共享鎖定。一個查詢記錄的語句必須在沒有與共享鎖定互斥鎖定存在或等待互斥鎖定結束後,才能設定共享鎖定並提取資料(互斥不互斥就是鎖的相容性,這在以後再說明)。

    排它鎖定發生在對資料增加、刪除、修改時,事務開始以後語句申請並設定排它鎖定(前提是沒有其它互斥鎖定存在),以明確告知其它程序對當前資料不可以查詢或修改,等待事務結束後其它程序才可以查詢或修改。

    更新鎖定是一個介於共享與排它之間的中繼鎖定,比如我們帶where條件的update語句,在查詢要更新的記錄時是設定共享鎖定,當要更新資料時這時鎖定必須由共享鎖定升級成更新鎖定繼而升級為排它鎖定,當排它鎖定設定成功才可以進行資料修改操作。顯然也是要要求在鎖升級的過程中沒有互斥鎖定的存在。簡單的理解更新鎖定是一箇中繼閘一樣,把升級成排它鎖定程序“序列化”,以解決死鎖。最後重點說明一下,資料更新階段是要對資料排它鎖定不是更新鎖定,不要被字面意思訓導哦。

    最後說一下在上述鎖定模式下的互斥,共享鎖定只與排它鎖定互斥,更新鎖定只與共享鎖定不互斥。

    在進行具體例項前我們一定要有一個工具來對我們例項過程進行監控,好,下面我寫了一個過程,在需要時直接呼叫就行,過程如下:

Create Proc sp_us_lockinfo

---------------------------------------------------------------------

-- Author : HappyFlyStone

-- Date   : 2009-10-03 15:30:00

-- 申明    :請保留作者資訊,轉載註明出處

---------------------------------------------------------------------

AS

BEGIN

    SELECT

        DB_NAME(t1.resource_database_id) AS [資料庫名],

        t1.resource_type AS [資源型別],

    --    t1.request_type AS [請求型別],

        t1.request_status AS [請求狀態],

    --    t1.resource_description AS [資源說明],

       CASE t1.request_owner_type WHEN 'TRANSACTION' THEN '事務所有'

                                WHEN 'CURSOR' THEN '遊標所有'

                                WHEN 'SESSION' THEN '使用者會話所有'

                                WHEN 'SHARED_TRANSACTION_WORKSPACE' THEN '事務工作區的共享所有'

                                WHEN 'EXCLUSIVE_TRANSACTION_WORKSPACE' THEN '事務工作區的獨佔所有'

                                ELSE ''

       END AS [擁有請求的實體型別],

       CASE WHEN T1.resource_type = 'OBJECT'

           THEN OBJECT_NAME(T1.resource_ASsociated_entity_id)

           ELSE  T1.resource_type+':'+ISNULL(LTRIM(T1.resource_ASsociated_entity_id),'')

           END AS [鎖定的物件],

        t4.[name] AS [索引],

        t1.request_mode AS [鎖定型別],

        t1.request_session_id AS [當前spid],    

        t2.blocking_session_id AS [鎖定spid],

    --    t3.snapshot_isolation_state AS [快照隔離狀態],

        t3.snapshot_isolation_state_desc AS [快照隔離狀態描述],

        t3.is_read_committed_snapshot_on AS [已提交讀快照隔離]

    FROM

        sys.dm_tran_locks AS t1

    left join

        sys.dm_os_waiting_tasks AS t2

    ON

        t1.lock_owner_address = t2.resource_address

    left join

        sys.databases AS t3

    ON t1.resource_database_id = t3.database_id

    left join

       (

        SELECT rsc_text,rsc_indid,rsc_objid,b.[name]

       FROM

           sys.syslockinfo a

       JOIN

           sys.indexes b

       ON a.rsc_indid = b.index_id and b.object_id = a.rsc_objid) t4

    ON t1.resource_description = t4.rsc_text

END

GO

/*

呼叫示例:exec sp_us_lockinfo

*/

exec sp_us_lockinfo

/*

*/

drop proc sp_us_lockinfo

最後介紹一個隔離等級設定命令:

SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED

                                 | READ COMMITTED

                                 | REPEATABLE READ

                                 | SNAPSHOT

                                 | SERIALIZABLE}[;]

好,下面開始例項“快樂”之旅了。

五、隔離等級例項

測試資料準備:

CREATE DATABASE testcsdn;

GO

CREATE TABLE TA(TCID INT PRIMARY KEY,TCNAME VARCHAR(20))

INSERT TA SELECT 1,'AA'

INSERT TA SELECT 2,'AA'

INSERT TA SELECT 3,'AA'

INSERT TA SELECT 4,'BB'

INSERT TA SELECT 5,'CC'

INSERT TA SELECT 6,'DD'

INSERT TA SELECT 7,'DD'

GO

約定:以下提及的查詢N,都是開啟一個新連線執行查詢

1、 未提交讀(uncommitted Read)

概念回顧:未提交讀是最低等級的隔離,允許其它程序讀取本程序未提交的資料行,也就是讀取資料時不設定共享鎖定直接讀取,忽略已經存在的互斥鎖定。很顯然未提交讀這種隔離級別不會造成丟失更新,但是其它意外行為還是可以發生的。它和select 加鎖定提示NOLOCK效果相當。

測試例項:

查詢一:

SELECT * FROM TA WHERE TCID = 1

BEGIN TRAN

UPDATE TA

SET TCNAME = 'TA'

WHERE TCID = 1

--COMMIT TRAN --Don't commit

SELECT * FROM TA WHERE TCID = 1

SELECT @@SPID

/*

tcid        Tcname

----------- --------------------

1           AA

(1 行受影響)

(1 行受影響)

tcid        Tcname

----------- --------------------

1           TA

(1 行受影響)

SPID

------

54

(1 行受影響)

*/

查詢二:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

SELECT * FROM TA WHERE TCID = 1

/*

tcid        Tcname

----------- --------------------

1           TA

(1 行受影響)

*/

--顯然未提交讀模式我們讀到SPID=54未提交的資料。

查詢三:

SELECT * FROM TA WHERE TCID = 1

--查詢一直進行中…… 無結果

--因為預設下已提交讀級別,所以修改資料設定了排它鎖定必須等到SPID=54的事務結束

查詢四:

--檢視當前的鎖定資訊

exec sp_us_lockinfo

/*

*/

 
這個時候如果我們回頭到查詢一里執行commit tran ,你會發現查詢三會得到結果,並且是查詢一修改後的結果,如果你改用rollback ,那麼結果就是原來的值不變,這個你們自己再測試。

1、 已提交讀(Read Committed)

概念回顧:已提交讀是SQL SERVER的預設隔離級別,悲觀模型下是用鎖定,樂觀模型下使用行版本控制器。這個設定可以通過SET READ_CIMMITTED_SNAPSHOT來修改。在悲觀模型下對於讀取來說設定共享鎖定僅阻止排它鎖定,並在資料讀取結束自動釋放,其它程序方可進行修改操作。也就是說讀不會阻止其它程序設定共享及更新鎖定,僅阻止排它鎖定。在悲觀模型下對於修改資料來說設定排鎖定阻止所有鎖定請示,必須等到排它鎖定釋放。這個級別的隔離解決了髒讀的意外行為。

A、       READ_COMMITTED_SNAPSHOT為OFF的情況(預設)

I、讀資料測試

查詢一:

BEGIN TRAN

--用鎖定提示模擬共享鎖定,並強制共享鎖定持續到事務結束

SELECT * FROM TA with(holdlock) WHERE TCID = 1

--COMMIT TRAN --Don't commit

SELECT @@SPID

/*

tcid        Tcname

----------- --------------------

1           CA

(1 行受影響)

------

54

(1 行受影響)

*/

查詢二:悲觀模型下已提交讀級別

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

UPDATE TA

SET TCNAME = 'TA'

WHERE TCID = 1

--查詢一直沒有結果,顯然我們驗證了共享鎖定阻止了排它鎖定。

查詢三:

exec sp_us_lockinfo

--結果大家自己執行看結果。

II、修改資料測試

查詢一:

SELECT * FROM TA WHERE TCID = 1

BEGIN TRAN

UPDATE TA

SET TCNAME = 'READ COMMITTED LOCK'

WHERE TCID = 1

--COMMIT TRAN --Don't commit

SELECT @@SPID

/*

tcid        Tcname

----------- --------------------

1           TA

(1 行受影響)

------

54

相關推薦

SQL2005中的事務鎖定(四)

查詢一: DROP TABLE TB GO CREATE TABLE TB (ID INT Primary Key, COL VARCHAR(10)) GO INSERT INTO TB SELECT 1,'A' GO SET TRANSACTION ISOLATION LEVEL SERIALIZABL

SQL2005中的事務鎖定(一到九整合版)

      終於定下心來寫這個事務與鎖定的文章,下筆後才發現真的很難寫,交易中事務與鎖定這個話題過於複雜,甚至有些還摸不著(就是通過DMV或DMF或其它工具你可能很難看到它的蹤影),讓人有點讓人望而止步,但是既然說了要寫,似乎不繼續下去不是我的風格。在接下來的幾篇文章

SQL2005中的事務鎖定(九)-(二)- 轉載

ise clas iso state primary sql actions 內容 移除 -------------------------------------------------------------------------- Author : HappyFly

SQL2005中的事務鎖定(三)

查詢一: BEGIN TRAN --用鎖定提示模擬共享鎖定,並強制共享鎖定持續到事務結束 SELECT * FROM TA with(holdlock) WHERE TCID = 1 --COMMIT TRAN --Don't commit SELECT @@SPID /* tcidTc

事務鎖定

一、併發及併發控制模型     在資料庫併發就是多個程序同時取、存資料庫裡資料的能力。著眼我們開發的系統,當然是激動態的並互不打架的併發使用者程序越多併發能力就越強大啦,你想想看好多的網上購物系統,如果沒有併發處理的能力,那麼在上面登記的使用者資訊、商品有庫存資訊及使用者帳戶資訊很難保證正確性和

SQL2005中的事務鎖定(一)

------------------------------------------------------------------------ -- Author : HappyFlyStone -- Date: 2009-09-24 21:36:30 -- Versi

事務隔離級別筆記

講解 三種 span http ont nbsp 隔離 server bsp SQL Server 2008 R2 事務與隔離級別實例講解 筆記 1、事務是數據庫的工作單元,可視為一個原子操作,要麽成功,要麽什麽也不曾發生   事務操作的三種命令:     a、     事

【SQL Server學習筆記】事務鎖定、阻塞、死鎖

body sqlserve distrib reset reads cli ast function pre http://blog.csdn.net/sqlserverdiscovery/article/details/7712068 Column nameData

SQL Server中的事務

ani 否則 編譯 什麽 高並發 設置時間 檢測 isolation 管理 了解事務和鎖 事務:保持邏輯數據一致性與可恢復性,必不可少的利器。 鎖:多用戶訪問同一數據庫資源時,對訪問的先後次序權限管理的一種機制,沒有他事務或許將會一塌糊塗,不能保證數據的安全正確讀寫。 死鎖

分布式緩存技術redis學習系列(三)——redis高級應用(主從、事務鎖、持久化)

master ica not ood www working can 出了 owin 上文《詳細講解redis數據結構(內存模型)以及常用命令》介紹了redis的數據類型以及常用命令,本文我們來學習下redis的一些高級特性。 回到頂部 安全性設置 設置客戶端操作秘密

MySQL(二)--事務視圖

atom enc 消失 ability count 事務 統計 tran 操作 一、事務 1、提交 2、回滾 3、ACID特性 二、視圖 1、創建視圖 2、刪除視圖 3、更新視圖 4、使用視圖 三、子查詢 1、 使用子查詢

MySQL 事務鎖機制

mysql下表展示了本人安裝的MariaDB(10.1.19,MySQL的分支)所支持的所有存儲引擎概況,其中支持事務的有InnoDB、SEQUENCE,另外InnoDB還支持XA事務,MyISAM不支持事務。鎖可以通過SQL語句(如 LOCK TABLES )顯式申請,也可以由InnoDB引擎自動為你獲取。

編程式事務聲明式事務

lex scan 文件中 exc 案例演示 ans java 方法 -s 編程式事務 1.加入jar包 com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.ja

劍指架構師系列-InnoDB存儲引擎、Spring事務緩存

之前 ner 不提交 變化 def dto suspend 自己實現 更改 事務與鎖是不同的。事務具有ACID屬性: 原子性:持久性:由redo log重做日誌來保證事務的原子性和持久性,一致性:undo log用來保證事務的一致性隔離性:一個事務在操作過程中看到了其他

MySQL的事務事務隔離

mysql innodb transactions 事務隔離 MySQL中自從引入InnoDB引擎後,在MySQL中就支持事務,事務就是一組原子性的查詢語句,也即將多個查詢當作一個獨立的工作單元,平時通過提交工作單元來完成在事務中的相應的查詢或修改,在能支持事務的數據庫中必須要滿足ACI

【SQL】- 基礎知識梳理(八) - 事務

隔離性 rep del 數據表 訪問 關系 snapshot 轉換 pro 事務的概念 事務:若幹條T-SQL指令組成的一個操作數據庫的最小執行單元,這個整體要麽全部成功,要麽全部失敗。(並發控制) 事務的四個屬性:原子性、一致性、隔離性、持久性。稱為事務的ACID特性。

Java開發Redis的事務Watch原理分析

緬甸鉆石國際 開戶13378837779Redis中的業務(transaction)是一組指令的調集。業務同指令一樣都是Redis最小的履行單位,一個業務中的指令要麽都履行,要麽都不履行。Redis業務的完結需求用到 MULTI 和 EXEC兩個指令,業務開端的時分先向Redis服務器發送 MULTI 指

事務4.3-事務鎖(鎖)

sele 字段 防止 對數 實際應用 影響 功能 更新 read 數據庫和操作系統一樣,是一個多用戶使用的共享資源。當多個用戶並發地存取數據時,在數據庫中就會產生多個事務同時存取同一數據的情況。若對並發操作不加控制就可能會讀取和存儲不正確的數據,破壞數據庫的一致性。加鎖是實

SQL SERVER存儲過程中使用事務捕獲異常

log class url 開始 過程 eat rollback catch ack https://www.douban.com/note/559596669/ 格式類似於CREATE PROCEDURE YourProcedure ASBEGIN SET N

【SqlServer系列】淺談SQL Server事務鎖(上篇)

架構 tab 要求 允許 ble 1.2 定義 由於 數據庫引擎 一 概述 在數據庫方面,對於非DBA的程序員來說,事務與鎖是一大難點,針對該難點,本篇文章試圖采用圖文的方式來與大家一起探討。 “淺談SQL Server 事務與鎖”這個專題共分