• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Prayer

            在一般中尋求卓越
            posts - 1256, comments - 190, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            隔離級別和鎖

            Posted on 2010-03-17 09:46 Prayer 閱讀(738) 評論(0)  編輯 收藏 引用 所屬分類: 數據庫,SQLDB2

            我們在進行客戶支持時遇到最多的話題之一就是鎖。“為什么 DB2 鎖住了這個表、行或者對象?”,“這個鎖會阻塞多長時間及為什么?”;“為什么出現了死鎖?”,“我的鎖請求在等待什么?”,諸如此類問題等等。更仔細地分析一些常見的鎖示例可以說明DB2鎖定策略背后的原則。在國內很多DB2用戶都會碰到有關鎖等待、死鎖和鎖升級等鎖相關的問題,本章將會對這些問題以及解決方法做詳細的講解。

            本章主要講解如下內容:

            ●       隔離級別和鎖

            ●       加鎖總結

            ●       樂觀鎖

            ●       內部鎖

            ●       設置鎖相關的注冊變量

            6.1  隔離級別和鎖

            要維護數據庫的一致性和數據完整性,同時又允許多個應用程序同時訪問一個數據庫,將這樣的特性稱為并發性。DB2數據庫嘗試強制實施并發性的方法之一是使用隔離級別,它決定在第一個事務訪問數據時,如何對其他事務鎖定或隔離該事務所使用的數據。DB2使用下列隔離級別來強制實施并發性:

            ●       可重復讀(Reapeatable Read,RR)

            ●       讀穩定性(Read Stability,RS)

            ●       游標穩定性(Cursor Stability,CS)

            ●       未提交的讀(Uncommitted Read,UR)

            隔離級別是根據稱為現象(Phenomena)的三個禁止操作序列來聲明的:

            ●       臟讀(Dirty Read):在事務A提交修改結果之前,其他事務即可看到事務A的修改結果。

            ●       不可重復讀(Non-Repeatable Read):在事務A提交之前,允許其他事務修改和刪除事務A涉及的數據,導致事務A中執行同樣操作的結果集變小。

            ●       幻像讀(Phantom Read):事務A在提交查詢結果之前,其他事務可以插入或者更改事務A涉及的數據,導致事務A中執行同樣操作的結果集增大。

            數據庫并發性(可以同時訪問同一資源的事務數量)因隔離級別不同而有所差異,可重復讀隔離級別可以防止所有現象,但是會大大降低并發性。未提交讀隔離級別提供了最大的并發性,但可能會造成“臟讀”、“幻像讀”或“不可重復讀”現象。DB2默認的隔離級別是CS。

            6.1.1  可重復讀

            可重復讀隔離級別是最嚴格的隔離級別。在使用它時,一個事務的操作結果完全與其他并發事務隔離,臟讀、不可重復讀、幻像讀都不會發生。當使用可重復讀隔離級別時,在事務執行期間會共享(S)鎖定該事務以任何方式引用的所有行,在該事務中多次執行同一條SELECT語句,得到的結果數據集總是相同的。因此,使用可重復讀隔離級別的事務可以多次檢索同一行集,并可以對它們執行任意操作,直到提交或回滾操作終止事務。但是,在事務提交前,不允許其他事務執行會影響該事務正在訪問的任何行的插入、更新或刪除操作。為了確保這種行為,需要鎖定該事務所引用的每一行—— 而不是僅鎖定被實際檢索或修改的那些行。因此,如果一個表中有1000行,但只檢索兩行,則整個表(1000行,而不僅是被檢索的兩行)都會被鎖定。輸出結果如下:

            C:\>db2 +c select empno,firstnme,salary from employee where empno between '000010' and '000020' with  rr

            EMPNO  FIRSTNME     SALARY

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

            000010 CHRISTINE      152750.00

            000020 MICHAEL         94250.00

              2 條記錄已選擇。

            我們通過“get snapshot for locks on sample”命令來監控表加鎖情況,輸出結果如下:

            C:\>db2 update monitor switches using lock on

            DB20000I  UPDATE MONITOR SWITCHES命令成功完成。

            C:\>db2 get snapshot for locks on sample | more

            --------------略------------------

            鎖定列表

            鎖定名稱                       = 0x020006000E0040010000000052

            鎖定屬性                       = 0x00000010

            發行版標志                     = 0x00000004

            鎖定計數                       = 1

            掛起計數                       = 0

            鎖定對象名                     = 20971534

            對象類型                       = 表

            表空間名                       = USERSPACE1

            表模式                        = DB2ADMIN

            表名                         = EMPLOYEE

            方式                           = S    --注:雖然讀取了兩行,但是整個表加S鎖

            如果使用這種隔離級別,不管你從表中讀多少數據,整個表上都加S鎖,直到該事務被提交或回滾,表上的鎖才會被釋放。這樣可以保證在一個事務中即使多次讀取同一行,都會得到相同結果集。另外,在同一事務中如果以同樣的搜索標準重新打開已被處理過的游標,那么得到的結果集不會改變。可重復讀相對于讀穩定性而言,加鎖的范圍更大:對于讀穩定性,應用程序只對符合要求的所有行加鎖;而對于重復讀,應用程序將對整個表都加S鎖。

            可重復讀會鎖定應用程序在工作單元中引用的整個表。利用可重復讀,一個應用程序在打開游標的相同工作單元內發出一個SELECT語句兩次,每次都返回相同的結果。利用可重復讀隔離級別,不可能出現丟失更新、臟讀和幻像讀的情況。

            在該工作單元完成之前,“可重復讀”應用程序可以多次檢索和操作這些行。但是,在該工作單元完成之前其他應用程序均不能更新、刪除或插入可能會影響結果表的行。“可重復讀”應用程序不能查看其他應用程序未提交的更改。

            6.1.2  讀穩定性

            讀穩定性隔離級別沒有可重復讀隔離級別那么嚴格;因此,它沒有將事務與其他并發事務的效果完全隔離。讀穩定性隔離級別可以防止臟讀和不可重復讀,但是可能出現幻像讀。在使用這個隔離級別時,只鎖定事務實際檢索和修改的行。因此,如果一個表中有1000行,但只檢索兩行(通過索引掃描),則只鎖定被檢索的兩行(而不是所掃描的 1000 行)。因此,如果在同一個事務中發出同一個SELECT語句兩次或更多次,那么每次產生的結果數據集可能不同。

            與可重復讀隔離級別一樣,在讀穩定性隔離級別下運行的事務可以檢索一個行集(ROWS SET),并可以對它們執行任意操作,直到事務終止。在這個事務存在期間,其他事務不能執行那些會影響這個事務檢索到的行集的更新或刪除操作,但是可以執行插入操作。如果插入的行與第一個事務的查詢的選擇條件匹配,那么這些行可能作為幻像出現在后續產生的結果數據集中。其他事務對其他行所作的更改,在提交之前是不可見的。下面我們還用上面的那個例子鎖定讀穩定性,輸出結果如下:

            C:\>db2 +c select empno,firstnme,salary from employee where empno between '000010' and '000020' with  rs

            EMPNO  FIRSTNME     SALARY

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

            000010 CHRISTINE      152750.00

            000020 MICHAEL         94250.00

              2 條記錄已選擇。

            我們通過“get snapshot for locks on sample”命令來監控表加鎖情況,輸出結果如下:

            C:\>db2 update monitor switches using lock on

            DB20000I  UPDATE MONITOR SWITCHES命令成功完成。

            C:\>db2 get snapshot for locks on sample | more

            --------------略------------------

            鎖定列表

            鎖定名稱                       = 0x02000600050040010000000052

            鎖定屬性                       = 0x00000010

            發行版標志                     = 0x00000001

            鎖定計數                       = 1

            掛起計數                       = 0

            鎖定對象名                     = 20971525

            對象類型                       = 行

            表名                      = EMPLOYEE

            方式                           = S --注:只在讀取的行上加S鎖

            鎖定名稱                       = 0x02000600040040010000000052

            鎖定屬性                       = 0x00000010

            發行版標志                     = 0x00000001

            鎖定計數                       = 1

            掛起計數                       = 0

            鎖定對象名                     = 20971524

            對象類型                       = 行

            表名                      = EMPLOYEE

            方式                           = S --注:只在讀取的行上加S鎖

            鎖定名稱                       = 0x02000600000000000000000053

            鎖定屬性                       = 0x00000010

            發行版標志                     = 0x00000001

            鎖定計數                       = 1

            掛起計數                       = 0

            鎖定對象名                     = 6

            對象類型                       = 表

            表名                      = EMPLOYEE

            方式                           = IS --注:表上加IS鎖

            如果使用這種隔離級,那么在一個事務中將有N+1個鎖,其中N是所有被讀取(通過索引掃描)過的行的數目,這些行上都會被加上NS鎖,在表上加上1個IS鎖。這些鎖直到該事務被提交或回滾才會被釋放。這樣可以保證在一個事務中即使多次讀取同一行,得到的值也不會改變。但是使用這種隔離級別,在一個事務中,如果使用同樣的搜索標準重新打開已被處理過的游標,則結果集可能改變(可能會增加某些行,這些行被稱為幻影行(Phantom))。這是因為RS隔離級別不能阻止通過插入或更新操作在結果集中加入新行。

            注意:

            NS是下一鍵共享鎖,此時鎖擁有者和所有并發的事務都可以讀(但不能更改)被鎖定行中的數據。這種鎖用來在使用讀穩定性或游標穩定性事務隔離級別讀取的數據上代替共享鎖。

            讀穩定性(RS)只鎖定應用程序在工作單元中檢索的那些行。它確保在某個工作單元完成之前,在該工作單元運行期間的任何限定行讀取不被其他應用程序進程更改,且確保不會讀取由另一個應用程序進程所更改的任何行,直至該進程提交了這些更改。也就是說,不可能出現“不可重復讀”情形。

            “讀穩定性”隔離級別的其中一個目標是提供較高并行性以及數據的穩定視圖,為了有助于達到此目標,優化器確保在發生鎖定升級前不獲取表級鎖定。

            “讀穩定性”隔離級別最適用于包括下列所有特征的應用程序:

            ●       在并發環境下運行。

            ●       需要限定某些行在工作單元運行期間保持穩定。

            ●       在工作單元中不會多次發出相同的查詢,或者在同一工作單元中發出多次查詢時并不要求該查詢獲得相同的回答。

            6.1.3  游標穩定性

            游標穩定性隔離級別在隔離事務效果方面非常寬松。它可以防止臟讀;但有可能出現不可重復讀和幻像讀。這是因為在大多數情況下,游標穩定性隔離級別只鎖定事務聲明并打開的游標當前引用的行。

            當使用游標穩定性隔離級別的事務通過游標從表中檢索行時,其他事務不能更新或刪除游標所引用的行。但是,如果被鎖定的行本身不是用索引訪問的,那么其他事務可以將新的行添加到表中,以及對被游標鎖定行前后的行進行更新或刪除操作。所獲取的鎖一直有效,直到游標重定位或事務終止為止(如果游標重定位,原來行上的鎖就被釋放,并獲得游標現在引用的行上的鎖)。此外,如果事務修改了它檢索到的任何行,那么在事務終止之前,其他事務不能更新或刪除該行,即使在游標不再位于被修改的行時。與可重復讀和讀穩定性隔離級別一樣,其他事務在其他行上進行的更改,在這些更改提交之前對于使用游標穩定性隔離級別的事務(這是默認的隔離級別)是不可見的。我們還用上面那個例子,一個表中有1000行數據,我們只檢索其中兩行數據。那么對于可重復讀隔離級別會鎖住整個表,對于讀穩定性隔離級別會對讀到的數據(兩行)加鎖,而對于游標穩定性隔離級別只對游標當前所在那一行加鎖,游標所在行的前一行和下一行都不加鎖。下面我們舉一個游標穩定性的例子,輸出結果如下:

            C:\>db2 +c declare c1 cursor for  select empno,firstnme,salary from employee where empno between '000010' and '000020' with cs

            C:\>db2 +c open c1

            C:\>db2 +c fetch c1

            EMPNO   FIRSTNME      SALARY

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

            000010 CHRISTINE      152750.00   --注:游標當前所在行,DB2只對這一行加鎖。游標的

            上一行和下一行都不加鎖。當游標移動到下一行時,鎖自動釋放。

              1 條記錄已選擇。

            我們通過“get snapshot for locks on sample”命令來監控表加鎖情況,輸出結果如下:

            C:\>db2 update monitor switches using lock on

            DB20000I  UPDATE MONITOR SWITCHES命令成功完成。

            C:\>db2 get snapshot for locks on sample | more

            --------------略------------------

            鎖定名稱                         = 0x02000600040040010000000052

            鎖定屬性                         = 0x00000010

            發行版標志                       = 0x00000001

            鎖定計數                         = 1

            掛起計數                         = 0

            鎖定對象名                       = 20971524

            對象類型                       = 行

            表名                          = EMPLOYEE

            方式                             = S --注:只在游標所在行上加S鎖

            鎖定名稱                         = 0x02000600000000000000000053

            鎖定屬性                         = 0x00000010

            發行版標志                       = 0x00000001

            鎖定計數                         = 1

            掛起計數                         = 0

            鎖定對象名                       = 6

            對象類型                       = 表

            表名                            = EMPLOYEE

            方式                            = IS --注:表上加IS鎖

            如果使用這種隔離級,那么在一個事務中只有兩個鎖:結果集中只有正在被讀取的那一行(游標指向的行)被加上NS鎖,在表上加IS鎖。其他未被處理的行上不加鎖。這種隔離級別只能保證正在處理的行的值不會被其他并發的程序所改變。該隔離級別是DB2默認的隔離級別。

            游標穩定性(CS)當在行上定位游標時會鎖定任何由應用程序的事務所訪問的行。此鎖定在讀取下一行或終止事務之前有效。但是,如果更改了某一行上的任何數據,那么在對數據庫提交更改之前必須掛起該鎖定。

            對于具有“游標穩定性”的應用程序已檢索的行,當該行上有任何可更新的游標時,任何其他應用程序都不能更新或刪除該行。“游標穩定性”應用程序不能查看其他應用程序的未提交操作。

            使用“游標穩定性”,可能會出現不可重復讀和幻像讀現象。“游標穩定性”是默認隔離級別,應在需要最大并行性,但只看到其他應用程序中的已提交行的情況下才使用。

            6.1.4  未提交讀

            未提交讀隔離級別是最不嚴格的隔離級別。實際上,在使用這個隔離級別時,僅當另一個事務試圖刪除或更改被檢索的行所在的表時,才會鎖定一個事務檢索的行。因為在使用這種隔離級別時,行通常保持未鎖定狀態,所以臟讀、不可重復讀和幻像讀都可能會發生。因此,未提交讀隔離級別通常用于那些訪問只讀表和視圖的事務,以及某些執行SELECT語句的事務(只要其他事務的未提交數據對這些語句沒有負面效果)。

            顧名思義,其他事務對行所做的更改在提交之前對于使用未提交讀隔離級別的事務是可見的。但是,此類事務不能看見或訪問其他事務DDL(CREATE、ALTER和DROP)語句所創建的表、視圖或索引,直到那些事務被提交為止。類似地,如果其他事務刪除了現有的表、視圖或索引,那么僅當進行刪除操作的事務終止時,使用未提交讀隔離級別的事務才能知道這些對象不再存在了。

            一定要注意一點:當運行在未提交讀隔離級別下的事務使用可更新游標時,該事務的行為和在游標穩定性隔離級別下運行一樣,并應用游標穩定性隔離級別的約束。下面我們舉一個例子。

            我們編寫一個SQL存儲過程,在存儲過程中我們顯式地在SELECT語句中使用UR隔離級別。

            創建一個存儲過程,保存為LOCKS.SQL,輸出結果如下:

            CREATE PROCEDURE locks()

            LANGUAGE SQL

            BEGIN

            declare c1 cursor for select * from staff with UR;

            open c1;

            while 1=1 do ——注:死循環

            end while;

            END @

            為了方便抓住鎖信息,我們在這個存儲過程的結尾處使用了一個死循環。利用一個命令窗口運行存儲過程,輸出結果如下:

            C:\ >db2 –td@ -vf locks.sql

            C:\ >db2 "call locks()"

            再打開一個新的窗口,得到在STAFF表上的當前鎖信息,輸出結果如下:

            C:\>db2pd -db sample -locks show detail

            Locks:

            Address TranHdl Lockname Type Mode Sts Owner Dur HldCnt Att ReleaseFlg

            0x408E0290 2 00020003000000000000000054 Table .IS G 2 1 0 0x0000 0x00000001

            TbspaceID 2 TableID 3

            但是會發現此時在STAFF表上出現的是IS鎖,而不是IN鎖。是什么原因呢?這是因為UR隔離級別允許應用程序存取其他事務的未落實的更改,但是對于只讀和可更新這兩種不同的游標類型,UR的工作方式有所不同。對于可更新的游標,當它使用隔離級別 UR 運行程序時,應用程序會自動使用隔離級別 CS。

            在上面的例子當中,雖然顯式地指定了SQL語句的隔離級別是UR,但是,由于在存儲過程中使用的游標是模糊游標(也就是沒有顯式地聲明游標是只讀的還是可更新的),因而系統會默認地將這個模糊游標當成可更新游標處理,存儲過程的隔離級別自動從UR升級為CS。要防止此升級,可以采用以下辦法:

            ●       修改應用程序中的游標,以使這些游標是非模糊游標。將SELECT語句更改為包括FOR READ ONLY子句。

            ●       將模糊游標保留在應用程序中,但是預編譯程序或使用BLOCKING ALL和STATIC READONLY YES選項綁定它以允許在運行該程序時將任何模糊游標視為只讀游標。

            我們還是使用上面的例子,顯式地將該游標聲明成只讀游標,輸出結果如下:

            declare c1 cursor for select * from staff for read only with UR;

            此時我們再運行這個存儲過程,并利用DB2PD獲取鎖的情況,輸出結果如下:

            c:\> db2pd -db sample -locks show locks

            Locks:

            Address TranHdl Lockname Type Mode Sts Owner Dur HldCnt Att ReleaseFlg

            0x408E07E0 2 00020003000000000000000054 Table .IN G 2 1 0 0x0000 0x00000001

            TbspaceID 2 TableID 3

            -注:可以看到STAFF表上出現的鎖是IN鎖。

            從上面的例子中我們可以看到:“未提交讀(UR)”隔離級別允許應用程序訪問其他事務的未提交的更改。除非其他應用程序嘗試刪除或改變該表,否則該應用程序也不會鎖定正讀取的行而使其他應用程序不能訪問該行。對于只讀和可更新的游標,“未提交的讀”的工作方式有所不同。

            如果使用這種隔離級別,那么對于只讀操作不加行鎖。典型的只讀操作包括:               SELECT語句的結果集只讀(比如語句中包括ORDER BY子句);定義游標時指明起為FOR FETCH ONLY或FOR READ ONLY。

            該隔離級別可以改善應用程序的性能,同時可以達到最大程度的并發性。但是,應用程序的數據完整性將受到威脅。如果需要讀取未提交的數據,該隔離級是唯一選擇。

            使用“未提交的讀”,可能出現不可重復讀行為和幻像讀現象。“未提交讀”隔離級別最常用于只讀表上的查詢,或者在僅執行選擇語句且不關心是否可從其他應用程序中看到未提交的數據時也最常用。

            以上我們所講的隔離級別的加鎖范圍和持續時間都是針對讀操作而言的。對于更改操作,被修改的行上會被加上X鎖,無論使用何種隔離級別,X鎖都直到提交或回滾之后才會被釋放。

            6.1.5  隔離級別加鎖示例講解

            假設有一張表EMP1,表中有42條記錄,我們使用FOR READ ONLY分別在UR、CS、RS和RR隔離級別下加鎖。

            EMP1表在本章后續的內容中也會使用到,其創建過程如下:

            C:\> db2 "create table emp1 like employee"

            C:\> db2 "insert into emp1 select * from employee"

            我們使用EMP1表中JOB字段內容為'CLERK'的數據,輸出結果如下:

            C:\>db2 +c select empno,job,salary from emp1 where job='CLERK'  for read only

            EMPNO  JOB      SALARY

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

            000120 CLERK       49250.00

            000230 CLERK       42180.00

            000240 CLERK       48760.00

            000250 CLERK       49180.00

            000260 CLERK       47250.00

            000270 CLERK       37380.00

            200120 CLERK       39250.00

            200240 CLERK       37760.00

              8 條記錄已選擇。

            在上面的SQL語句中,我們從表的42條記錄中返回8條記錄。下面我們分別看看這條語句在不同的隔離級別下加鎖的情況:

            ●       UR隔離級別,輸出結果如下:

            C:\>db2 +c select empno,job,salary from emp1 where job='CLERK'  for read only with ur

            EMPNO  JOB        SALARY

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

            000120 CLERK       49250.00

            000230 CLERK       42180.00

            000240 CLERK       48760.00

            000250 CLERK       49180.00

            000260 CLERK       47250.00

            000270 CLERK       37380.00

            200120 CLERK       39250.00

            200240 CLERK       37760.00

              8 條記錄已選擇。

            在另外一個窗口中使用“db2 get snapshot for locks on sample”命令監控,發現在UR隔離級別下,在表上有一個IN鎖,沒有加任何行鎖。

            ●       CS隔離級別,輸出結果如下:

            C:\>db2 +c declare c1 cursor for select empno,job,salary from emp1  where job='CLERK'  for read only with CS

            C: \>db2 +c open c1

            C: \>db2 +c fetch c1

            EMPNO  JOB        SALARY

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

            000120 CLERK       49250.00

              1 條記錄已選擇。

            在另外一個窗口中使用“db2 get snapshot for locks on sample”命令監控,發現在CS隔離級別下,共有兩個鎖:在表上有一個IS鎖,在行上有一個NS鎖。

            ●       RS隔離級別,輸出結果如下:

            C:\>db2 +c select empno,job,salary from emp1 where job='CLERK'  for read only with RS

            EMPNO  JOB      SALARY

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

            000120 CLERK       49250.00

            000230 CLERK       42180.00

            000240 CLERK       48760.00

            000250 CLERK       49180.00

            000260 CLERK       47250.00

            000270 CLERK       37380.00

            200120 CLERK       39250.00

            200240 CLERK       37760.00

              8 條記錄已選擇。

            在另外一個窗口中使用“db2 get snapshot for locks on sample”命令監控,發現在RS隔離級別下,共有9個鎖:在表上有一個IS鎖,在讀取的8行上分別有1個NS鎖。

            ●       RR隔離級別,輸出結果如下:

            C:\>db2 +c select empno,job,salary from emp1 where job='CLERK'  for read only with RR

            EMPNO  JOB       SALARY

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

            000120 CLERK     49250.00

            000230 CLERK     42180.00

            000240 CLERK     48760.00

            000250 CLERK     49180.00

            000260 CLERK     47250.00

            000270 CLERK     37380.00

            200120 CLERK     39250.00

            200240 CLERK     37760.00

              8 條記錄已選擇。

            在另外一個窗口中使用“db2 get snapshot for locks on sample”命令監控,發現在RR隔離級別下,分為兩種情況:

            如果該SQL語句使用全表掃描,那么即使只讀取了8行,也會在整個表上加一個S鎖,輸出結果如下:

            C:\>dynexpln -d sample -q  "select empno,job,salary from emp1 where job='CLERK'

             for read only with rr" –t

            Access Table Name = DB2ADMIN.EMP1  ID = 3,12

            |  #Columns = 2

            |  Relation Scan --注:全表掃描

            |  |  Prefetch: Eligible

            |  Isolation Level: Repeatable Read --注:RR隔離級別

            |  Lock Intents

            |  |  Table: Share --注:整個表上加S鎖

            |  |  Row  : None

            |  Sargable Predicate(s)

            |  |  #Predicates = 1

            |  |  Return Data to Application

            |  |  |  #Columns = 3

            Return Data Completion

            End of section

            如果創建索引,并進行索引掃描,那么表上加IS鎖,讀取的每行上加S鎖。所以對于RR隔離級別來說,為了保證并發,盡可能創建合理的索引以減少加鎖的范圍,輸出結果如下:

            C:\>db2 create index job on DB2ADMIN.emp1(job)

            DB20000I  SQL命令成功完成。

            C:\>db2 runstats on table DB2ADMIN.emp1 and indexes all

            DB20000I  RUNSTATS命令成功完成。

            C:\>dynexpln -d sample -q  "select empno,job,salary from emp1 where job='CLERK'

             for read only with rr" -t

            Access Table Name = DB2ADMIN.EMP1  ID = 3,12

            |  Index Scan:  Name = DB2ADMIN.JOB  ID = 1 --注:索引掃描

            |  |  Regular Index (Not Clustered)

            |  |  Index Columns:

            |  |  |  1: JOB (Ascending)

            |  #Columns = 2

            |  #Key Columns = 1

            |  |  Start Key: Inclusive Value

            |  |  |  |  1: 'CLERK   '

            |  |  Stop Key: Inclusive Value

            |  |  |  |  1: 'CLERK   '

            |  Data Prefetch: Eligible 0

            |  Index Prefetch: None

            |  Isolation Level: Repeatable Read --注:RR隔離級別

            |  Lock Intents

            |  |  Table: Intent Share --注:表上加IS鎖

            |  |  Row  : Share --注:行上加S鎖

            |  Sargable Predicate(s)

            |  |  Return Data to Application

            |  |  |  #Columns = 3

            Return Data Completion

            End of section

            6.1.6  隔離級別摘要

            表6-1按不期望的結果概述了幾個不同的隔離級別。

            表6-1  隔離級別摘要

            隔離級別

            訪問未提交的數據

            不可重復讀

            幻像讀現象

            可重復讀(RR)

            不可能

            不可能

            不可能

            讀穩定性(RS)

            不可能

            不可能

            可能

            游標穩定性(CS)

            不可能

            可能

            可能

            未提交讀(UR)

            可能

            可能

            可能

            表6-2提供了簡單的試探方法,以幫助您為應用程序選擇初始隔離級別。首先考慮表中列示的方法,并參閱先前對影響各隔離級別因素的討論,可能會找到另一個更適合的隔離級別。

            表6-2  選擇隔離級別的準則

            應用程序類型

            需要高數據穩定性

            需要高數據穩定性

            讀寫事務

            RS

            CS

            只讀事務

            RR 或 RS

            UR

            為避免應用程序出現用戶無法容忍的現象,必須為其選擇適當的隔離級別。在不同隔離級別下,應用程序鎖定或釋放資源需要不同的CPU和內存資源,所以隔離級別不但影響應用程序之間的隔離程度,還可能影響應用程序的個別性能特征。潛在的鎖等待情況也會隨隔離級別的不同而不同。

            因為隔離級別確定訪問數據時如何鎖定數據并使數據不受其他進程影響,所以您在選擇隔離級別時應該平衡并行性和數據完整性需求。您指定的隔離級別在工作單元運行期間生效。

            選擇正確的隔離級別

            使用的隔離級別不僅影響數據庫的并發性,而且影響并發應用程序的性能。通常,使用的隔離級別越嚴格,并發性就越小,某些應用程序的性能可能會隨之越低,因為它們要等待資源上的鎖被釋放。那么,如何決定要使用哪種隔離級別呢?最好的方法是先確定哪些現象是不可接受的,然后選擇能夠防止這些現象發生的隔離級別。以下列舉了各種隔離級別的適用情況:

            ●       如果正在執行大型查詢,而且不希望并發事務所做的修改導致查詢的多次運行返回不同的結果,則使用可重復讀隔離級別。

            ●       如果希望在應用程序之間獲得一定的并發性,還希望限定的行在事務執行期間保持穩定,則使用讀穩定性隔離級別。

            ●       如果希望獲得最大的并發性,同時不希望查詢看到未提交的數據,則使用游標穩定性隔離級別。

            ●       如果正在只讀的表/視圖/數據庫上執行查詢,或者并不介意查詢是否返回未提交的數據,則使用未提交讀隔離級別。

            設置隔離級別

            盡管隔離級別控制事務級上的行為,但實際上它們是在應用程序級被指定的:

            ●       對于嵌入式SQL應用程序,在預編譯時或在將應用程序綁定到數據庫(如果使用延遲綁定)時指定隔離級別。在這種情況下,使用PRECOMPILE或BIND命令的ISOLATION選項來設置隔離級別。

            ●       對于開放數據庫連接(ODBC)和調用級接口(Call Level Interface,CLI)應用程序,隔離級別是在應用程序運行時通過調用指定了SQL_ATTR_TXN_ISOLATION連接屬性的SQLSetConnectAttr()函數進行設置的。另外,也可以通過指定DB2CLI.INI配置文件中的TXNISOLATION關鍵字的值來設置ODBC/CLI應用程序的隔離級別;但是,這種方法不夠靈活,不能像第一種方法那樣為一個應用程序中的不同事務修改隔離級別。

            ●       對于Java數據庫連接(JDBC)和SQLJ應用程序,隔離級別是在應用程序運行時通過調用DB2的JAVA.SQL連接接口中的“setTransactionIsolation()”方法設置的。

            當沒有使用這些方法顯式指定應用程序的隔離級別時,默認使用游標穩定性(CS)隔離級別。這個默認設置被應用于從命令行處理程序(CLP)執行的DB2 命令、SQL語句和腳本,以及嵌入式SQL、ODBC/CLI、JDBC和SQLJ應用程序。因此,也可以為從CLP執行的操作(以及傳遞給DB2 CLP進行處理的腳本)指定隔離級別。在這種情況下,隔離級別是通過在建立數據庫連接之前在CLP中執行CHANGE ISOLATION命令設置的,輸出結果如下:

            C:\pp>db2 change isolation to ur

            DB21027E  當連接至數據庫時未能更改隔離級別。

            C:\pp>db2 connect reset

            DB20000I  SQL命令成功完成。

            C:\pp>db2 change isolation to ur

            DB21053W  當連接至不支持 UR 的數據庫時,會發生自動升級。

            DB20000I  CHANGE ISOLATION命令成功完成。

            在DB2 V7.1及更高版本中,能夠指定特定查詢所用的隔離級別,方法是在SELECT SQL語句中加上WITH [RR | RS | CS | UR]子句。大家可以看到,本章前面的示例均使用這種方法舉例。

            日本精品久久久久中文字幕8| 亚洲国产成人精品91久久久 | 久久精品国产日本波多野结衣| 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 久久精品国产亚洲77777| 99麻豆久久久国产精品免费| 精品久久国产一区二区三区香蕉 | 久久精品青青草原伊人| 国产91色综合久久免费| 亚洲国产视频久久| 99久久精品免费看国产免费| 7777精品久久久大香线蕉| 国产99久久久国产精免费| 日韩人妻无码一区二区三区久久 | 国产99久久久久久免费看| 久久亚洲国产精品成人AV秋霞| 日韩精品久久无码人妻中文字幕| 久久精品国产精品青草app| A级毛片无码久久精品免费| 久久综合久久鬼色| 国产激情久久久久影院小草 | 久久99久久成人免费播放| 国产精品99久久99久久久| 狠狠色综合网站久久久久久久高清 | 久久亚洲AV无码精品色午夜| 精品久久久久久国产免费了| 久久久久久免费一区二区三区| 一本色道久久99一综合| 国内精品久久国产| 中文字幕久久亚洲一区| 四虎影视久久久免费观看| 久久综合狠狠综合久久97色| 国产精品激情综合久久| 国产精品内射久久久久欢欢 | 亚洲国产成人精品女人久久久 | 久久国产精品波多野结衣AV| 久久99中文字幕久久| 国产精品成人99久久久久 | 久久香蕉超碰97国产精品| 亚洲国产精品18久久久久久| 久久综合综合久久狠狠狠97色88|