<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 134,comments - 22,trackbacks - 0

    對象

         :每條SQL語句

         隔離:事務(wù)

    并發(fā)問題

    丟失更新

    未確認(rèn)的讀取(臟讀)

    不一致的分析(非重復(fù)讀):多次讀取相同的數(shù)據(jù)(行)不一致(其他用戶更改update

    幻像讀:多次讀取有不存在和新增的數(shù)據(jù)(其他用戶插入insert或刪除delete

    隔離級別

    隔離級別

    臟讀

    不可重復(fù)讀取

    幻像

    說明

    未提交讀(read uncommitted)

    如果其他事務(wù)更新,不管是否提交,立即執(zhí)行

    提交讀(read committed默認(rèn))

    讀取提交過的數(shù)據(jù)。如果其他事務(wù)更新沒提交,則等待

    可重復(fù)讀(repeatable read)

    查詢期間,不允許其他事務(wù)update

    可串行讀(serializable)

    查詢期間,不允許其他事務(wù)insert或delete

    提交讀

    假設(shè)存在表A,如下所示

    A1

    A2

    A3

    11

    21

    31

    12

    22

    32

    打開查詢分析器并打開兩個連接,分別輸入如下兩個事務(wù):

    --事務(wù)Ⅰ

    SET TRANSACTION ISOLATION LEVEL READ Committed

    begin tran

    update A set A2 = 20 where A1 = 11

    waitfor delay '00:00:10'

    rollback tran

    --事務(wù)Ⅱ

    SET TRANSACTION ISOLATION LEVEL READ Committed

    select * from A where A1 = 11

    如果先運(yùn)行事務(wù)Ⅰ,然后緊接著運(yùn)行事務(wù)Ⅱ,則事務(wù)Ⅱ要等待10秒鐘(一個連接在修改數(shù)據(jù)塊時別的連接也不能查詢這個數(shù)據(jù)塊,直到解。反之亦然:讀的時候不能寫和修改)。

    如果把事務(wù)Ⅱ改為如下

    SET TRANSACTION ISOLATION LEVEL READ UNCommitted

    select * from A where A1 = 11

    那么事務(wù)Ⅱ不需等待,立即執(zhí)行(可以看出READ UNCommitted事務(wù)select不對數(shù)據(jù)發(fā)出共享

    (這里主要講解 共享 排他 兩種經(jīng)常用到的)

    共享主要是為了共享讀(select),如果存在事務(wù)(一個或多個)擁有對表中數(shù)據(jù)(關(guān)于數(shù)據(jù)的多少,視的粒度而定)的共享,不允許對定的數(shù)據(jù)進(jìn)行更新(update)(從的角度講,即不允許事務(wù)獲取排他,要等到所有的共享都釋放掉)。反之,如果事務(wù)對數(shù)據(jù)已經(jīng)具有排他(只能有一個),其他的事務(wù)就不能對定的數(shù)據(jù)獲取共享和排他(即排他與共享不能兼容,更多信息請查看兼容性),在此特別強(qiáng)調(diào)一下 定的數(shù)據(jù) ,因為有的資料上講解到“一個連接寫的時候,另一個連接可以寫”,實(shí)際上寫的這種情況是各個連接的讀寫的數(shù)據(jù)不是相同的行,也就是說各個連接定的數(shù)據(jù)不同。

    根據(jù)以上分析,我們總結(jié)為六個字為“共享讀,排他寫”。

    了解了的情況之后,又涉及到一個問題。事務(wù)究竟要保持多久呢?

    一般來說,共享定時間與事務(wù)的隔離級別有關(guān),如果隔離級別Read Committed的默認(rèn)級別,只在讀取(select)的期間保持定,即在查詢出數(shù)據(jù)以后就釋放了;如果隔離級別為更高的Repeatable readSerializable,直到事務(wù)結(jié)束才釋放。另說明,如果select語句中指定了HoldLock提示,則也要等到事務(wù)結(jié)束才釋放

    排他直到事務(wù)結(jié)束才釋放。

    做出了以上分析,現(xiàn)在我們可能會存在這樣的疑問,到底在執(zhí)行SQL語句的時候發(fā)出什么樣的呢,這就由事務(wù)的隔離級別決定了。一般情況,讀語句(select)發(fā)出共享,寫語句(update,insert,delete)發(fā)出排他。但是,如果這樣不能滿足我們的要求怎么辦呢,有沒有更多選擇呢,別急,SQLserver為我們提供了定提示的概念。

           定提示對SQL語句進(jìn)行特別指定,這個指定將覆蓋事務(wù)的隔離級別。下面對各個定提示分別予以介紹(更多資料請查看SQLserver的聯(lián)機(jī)幫助),筆者做出了以下分類。

    類型1

         READUNCOMMITTED:不發(fā)出

         READCOMMITTED:發(fā)出共享,保持到讀取結(jié)束

         REPEATABLEREAD:發(fā)出共享,保持到事務(wù)結(jié)束

         SERIALIZABLE:發(fā)出共享,保持到事務(wù)結(jié)束

    類型2

         NOLOCK:不發(fā)出。等同于READUNCOMMITTED

         HOLDLOCK:發(fā)出共享,保持到事務(wù)結(jié)束。等同于SERIALIZABLE

         XLOCK:發(fā)出排他,保持到事務(wù)結(jié)束。

         UPDLOCK:發(fā)出更新,保持到事務(wù)事務(wù)結(jié)束。(更新:不阻塞別的事物,允許別的事物讀數(shù)據(jù)(即更新可與共享兼容),但他確保自上次讀取數(shù)據(jù)后數(shù)據(jù)沒有被更新

         READPAST:發(fā)出共享,但跳過定行,它不會被阻塞。適用條件:提交讀的隔離級別,行級select語句中。

    類型3

         ROWLOCK:行級

         PAGLOCK:頁級

         TABLOCK:表

         TABLOCKX:表排他

    講解完后,下面結(jié)合一個具體實(shí)例,具體看一下的使用。

           在很多系統(tǒng)中,經(jīng)常會遇到這種情況,要保持一個編號的唯一,如會計軟件中的憑證的編號。一種編號的處理是這樣的,把表中的最大編號保存到表中,然后在這個編號上累加,形成新的編號。這個過程對并發(fā)處理要求非常高,下面我們就來模擬這個過程,看如何保持編號的唯一性。

           新建一張表code來保存憑證的最大編號。字段如下:編號:bh(numeric(18,0)),憑證表名pinzheng(varchar(50))

    假設(shè)表中有這樣的一條記錄:

    Bh

    Pinzheng

    18000

    會計憑證

     

    新建一個存儲過程來生成新的憑證編號,如下:

    CREATE PROCEDURE up_getbh  AS

           Begin Tran

                  Declare @numnewbh numeric(18,0)

                  select  @numnewbh = bh FROM code  WITH (UPDLOCK,ROWLOCK) where pinzheng = '會計憑證'

                  set @numnewbh = @numnewbh + 1

                  update code set  bh = @numnewbh where pinzheng = '會計憑證'

                  print @numnewbh

           Commit tran

    GO

    然后,打開查詢分析器,并多開幾個連接(筆者開了8個連接,模擬有8個人同時并發(fā),讀者可以開更多的連接進(jìn)行試驗),把類似以下這樣的語句復(fù)制到每個連接窗口中,

    declare @i numeric(18,0)

    set @i = 1

    while @i = 1

    Begin

           if getdate() > '2004-07-22 14:23'  --設(shè)定一個時間,到此時間同時執(zhí)行upgetbh存儲過程

                  set @i = 0      

    end

    exec up_getbh

    然后,接連運(yùn)行各個連接,到2004-7-22 1423 這一刻,各個連接同時運(yùn)行up_getbh。從運(yùn)行結(jié)果可以看出連接順序出現(xiàn)18001開始個數(shù)字,并沒有重號或丟號的現(xiàn)象。

    分析:由于up_getbh中的select語句使用了更新,因更新之間不能兼容,所以各個連接要等到所有其他的連接釋放掉才能執(zhí)行,而更新的釋放要等到事務(wù)結(jié)束,這樣就不會發(fā)生號出錯的現(xiàn)象了。

    posted on 2010-02-04 15:01 何克勤 閱讀(741) 評論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫和SQL
    主站蜘蛛池模板: 一个人免费观看日本www视频| 久久精品视频免费看| 亚洲乱码日产一区三区| 性色午夜视频免费男人的天堂| 亚洲永久网址在线观看| 亚洲综合网站色欲色欲| 亚洲一区二区三区免费观看| 久久精品国产亚洲AV未满十八| 亚洲桃色AV无码| 日本特黄a级高清免费大片| 国产免费久久精品99久久| xxxx日本在线播放免费不卡| 亚洲综合日韩中文字幕v在线| 日韩精品免费一区二区三区| 久久er国产精品免费观看2| 99999久久久久久亚洲| 中文字幕亚洲不卡在线亚瑟| 国产精品69白浆在线观看免费| 一级一级一片免费高清| ass亚洲**毛茸茸pics| 国产AV无码专区亚洲AV漫画| 精品久久久久成人码免费动漫| 中文字幕免费在线视频| 国产亚洲精品影视在线| 亚洲视频在线一区| 怡红院免费的全部视频| 亚洲A∨精品一区二区三区下载| 亚洲丝袜美腿视频| 亚洲日本va午夜中文字幕久久| 毛片大全免费观看| 午夜不卡久久精品无码免费| 又粗又长又爽又长黄免费视频| 国产成人亚洲精品| 久久久国产精品亚洲一区| 亚洲午夜精品第一区二区8050| 免费黄色网址入口| 91免费资源网站入口| 一级毛片免费不卡在线| 两个人看的www免费高清 | 一区二区三区在线观看免费| 亚洲熟女综合一区二区三区|