關於併發控制

 

什麼是併發控制?

當許多人試圖同時修改數據庫中的數據時,必須實現一個控制系統,使一個人所做的修改不會對他人所做的修改產生負面影響。這稱爲併發控制。

簡單的理解就是2個或多個用者同時編輯相同的數據。這裏的用者可能是:實際用戶、不同服務、不同的代碼段(使用多線程),及其在斷開式和連接式情況下可能發生的情況。

併發控制理論根據建立併發控制的方法而分爲兩類:

悲觀併發控制(Pessimistic Concurrency)

一個鎖定系統,可以阻止用戶以影響其他用戶的方式修改數據。如果用戶執行的操作導致應用了某個鎖,只有這個鎖的所有者釋放該鎖,其他用戶才能執行與 該鎖衝突的操作。這種方法之所以稱爲悲觀併發控制,是因爲它主要用於數據爭用激烈的環境中,以及發生併發衝突時用鎖保護數據的成本低於回滾事務的成本的環 境中。

簡單的理解通常通過“獨佔鎖”的方法。獲取鎖來阻塞對於別的進程正在使用的數據的訪問。換句話說,讀者和寫者之間是會互相阻塞的 ,這可能導致數據同步衝突。

樂觀併發控制(Optimistic Concurrency)

在樂觀併發控制中,用戶讀取數據時不鎖定數據。當一個用戶更新數據時,系統將進行檢查,查看該用戶讀取數據後其他用戶是否又更改了該數據。如果其他 用戶更新了數據,將產生一個錯誤。一般情況下,收到錯誤信息的用戶將回滾事務並重新開始。這種方法之所以稱爲樂觀併發控制,是由於它主要在以下環境中使 用:數據爭用不大且偶爾回滾事務的成本低於讀取數據時鎖定數據的成本。

 

 

 

 

 

 

SQL server鎖的機制

SQL server的所有活動都會產生鎖。鎖定的單元越小,就越能越能提高併發處理能力,但是管理鎖的開銷越大。如何找到平衡點,使併發性和性能都可接受是SQL Server的難點。
SQL Server有如下幾種瑣:
1、 共享鎖
用於只讀操作(SELECT),鎖定共享的資源。共享鎖不會阻止其他用戶讀,但是阻止其他的用戶寫和修改。
2、 更新鎖
更新鎖是一種意圖鎖,當一個事物已經請求共享瑣後並試圖請求一個獨佔鎖的時候發生更新瑣。例如當兩個事物在幾行數據行上都使用了共享鎖,並同時試圖獲取獨佔鎖以執行更新操作時,就發生了死鎖:都在等待對方釋放共享鎖而實現獨佔鎖。更新鎖的目的是隻讓一個事物獲得更新鎖,防止這種情況的發生。
3、 獨佔鎖
一次只能有一個獨佔鎖用在一個資源上,並且阻止其他所有的鎖包括共享縮。寫是獨佔鎖,可以有效的防止’髒讀’
4、 意圖縮
在使用共享鎖和獨佔鎖之前,使用意圖鎖。從表的層次上查看意圖鎖,以判斷事物能否獲得共享鎖和獨佔鎖,提高了系統的性能,不需從爺或者行上檢查。
5、 計劃鎖
Sch-M,Sch-S。對數據庫結構改變時用Sch-M,對查詢進行編譯時用Sch-S。這兩種鎖不會阻塞任何事物鎖,包括獨佔鎖。

讀是共享鎖,寫是排他鎖,先讀後更新的操作是更新鎖,更新鎖成功並且改變了數據時更新鎖升級到排他鎖。鎖的類型有:
DB-----數據庫,由於 dbid 列已包含數據庫的數據庫 ID,所以沒有提供任何信息
FIL----文件
IDX----索引
PG-----頁,數據或索引頁。頁碼。頁由 fileid:page 組合進行標識,其中,fileid 是 sysfiles 表中的 fileid,而 page 是該文件內的邏輯頁碼。
KEY----鍵,用於保護可串行事務中的鍵範圍
TAB----表,包括所有數據和索引在內的整個表。由於 ObjId 列已包含表的對象 ID,所以沒有提供任何信息
EXT----區域, 相鄰的八個數據頁或索引頁構成的一組。正被鎖定的擴展盤區中的第一個頁碼。頁由 fileid:page 組合進行標識
RID----行,表內已鎖定行的行標識符。行由 fileid:page:rid 組合進行標識,其中,rid 是頁中的行標識符

鎖的狀態:
Grant---能使用被授權的資源
Wait----能使用被其他任務阻塞的資源
Cnvrt---Convert,鎖正在被轉換

細分鎖的模式:
0 Null 沒有得到資源的訪問權限
1 Sch-S (Schema stability) 對查詢進行編譯時。能防止加鎖的對象被刪除直到解鎖
2 Sch-M (Schema Modification) 改變數據庫結構時發生。能防止其他的事物訪問加鎖的對象
3 IS (Intent Shares) 意圖共享鎖。
4 SIU(Share Intent Update) 意圖在維護資源的共享鎖時,把更新鎖放到鎖層次結構的下層資源上
5 IS-S(Intent Share-shared) 複合鍵範圍鎖
6 IX(Intent Exclusive) 意圖排他鎖
7 SIX(Share Intent Exclusive)
8 S(Share) 共享鎖
9 U(Update) 更新鎖。防止死鎖
10 Iin-Nul(Intent Insert-Null) 索引行層次的鎖定,複合鍵範圍鎖
11 IS-X(Intent Share-Exclusive)
12 IU(Intent Update) 意圖更新鎖
13 IS-U(Intent Share Update) 串行更新掃描
14 X(Exclusive) 排他鎖
15 BU 塊操作使用的鎖

所以有如下的結論。

1、一個連接在修改數據塊時別的連接不能修改這個數據塊,直到解鎖。
並行訪問是任何數據庫解決方案都最爲重視的問題了,爲了解決並行訪問方面的問題各類數據庫系統提出了各種各樣的方案。SQL Server採用了多線程機制,它當然能夠一次處理多個請求。不過,在用戶修改數據的情況下並行訪問問題就變得複雜起來了。顯然,數據庫通常只允許唯一用戶一次修改特定的數據。當某一用戶開始修改某塊數據時, SQL Server能很快地鎖定數據,阻止其他用戶對這塊數據進行更新,直到修改該數據的第一位用戶完成其操作並提交交易或者回滾。但是,當某一位用戶正在修改某塊數據時假設另一位用戶又正想查詢該數據的信息時會發生什麼情況呢?
2、通常情況下,一個連接在修改數據塊時別的連接也不能查詢這個數據塊,直到解鎖。反之亦然:讀的時候不能寫和修改。這個方案會降低系統的性能和效率,儘管現在是行級鎖(7.0以前是鎖頁甚至是鎖表),如果你一次修改多行數據,SQL Server則會把數據鎖定範圍提升到頁級別乃至鎖定整個數據表,從而不必針對每一記錄跟蹤和維護各自的數據鎖,這樣能加快修改的速度,消耗小的服務器資源,但是併發性就差了。。
3、一個連接寫的時候,另一個連接可以寫,但是不得讀
4、多個連接可以同時讀同一行。

所以鎖發生在讀、寫的競爭上。

5、設置事物的級別 SET TRANSACTION ISOLATION LEVEL
A、READ COMMITTED :指定在讀取數據時控制共享鎖以避免髒讀,但數據可在事務結束前更改,從而產生不可重複讀取或幻像數據。該選項是 SQL Server 的默認值。
B、READ UNCOMMITTED:執行髒讀或 0 級隔離鎖定,這表示不發出共享鎖,也不接受排它鎖。當設置該選項時,可以對數據執行未提交讀或髒讀;在事務結束前可以更改數據內的數值,行也可以出現在數據集中

本篇文章來源於 [教程學習網] 轉載請以鏈接形式註明出處

 

 

 

 

關於oracle 鎖機制鎖問題的詳細分析(處理鎖定),以及死鎖的解決方案
在任何多用戶數據庫應用中,最終必然會出現兩個用戶希望同時處理相同記錄的情況.這種情況在邏輯上是不可能的,並且數據庫必須確保其在物理上也是不可能的.事務隔離性原則要求數據庫保證:在 ,這個會話無法影響另一個會話,並且後者也無法看到前者.爲了實現這個要求,數據庫創行話併發的數據訪問,甚至在多個會話請求訪問相同的記錄時,數據庫也必須確保這些會話排隊依次進行.
藉助於記錄和表鎖定機制,我們可以實現併發的串行化.oracle數據庫中的鎖定是完全自動的.一般而言,只有在試圖結合軟件與自動鎖定機制是或者編程人員編寫的代碼太糟糕時纔會引發某些問題.


                                                 共享鎖與排他鎖
 
oracle數據庫中鎖定的標準級別保證了最大可能的併發級別也就是說,如果某個會話正在更新一條記錄,那麼只有這條記錄會被鎖定.此外,鎖定這條記錄是爲了防止其他會話對其進行更新,其他會話可以隨時執行讀取操作.只有在使用commit或rollback命令結束事務之後,鎖定纔會被解除.這種鎖定是一個”排他鎖”:在指定記錄上請求排他鎖的第一個會話會得到這個鎖定,其他請求對該記錄進行寫訪問的會話則必須等待.雖然這條記錄已通過鎖定會話進行了更新,但是對其進行讀訪問你是被允許的(而且經常會出現這種情況),並且這些讀操作會涉及撤銷數據的使用,從而確保都會回並不會看到任何未被提交的變化
對於一條記錄或一個完整表上的一個排他鎖來說,每次只能有一個會話可以獲得這個排他鎖,不過許多會話可以同時獲得相同對象上的”共享鎖”.在一條記錄上設置共享鎖毫無意義,其原因在於鎖定一條記錄的唯一目的就是不允許其他會話更改它.共享鎖被置於整個表上,同時許多會話可以獲得同一個表上的共享鎖.在一個表上放置共享鎖的目的是爲了防止另一個會話獲得這個表上的排他鎖(在已存在共享鎖的情況下無法再獲得排他鎖).在表上防止排他鎖是需要執行DDL語句.如果其他任何會話已經在一個表上放置了共享鎖,那麼我們就無法執行修改某個對象的語句(例如刪除這個表的某一列).
爲了在記錄上執行DML語句,當前會話必須獲取待更新記錄上的排他鎖以及包含這些記錄的表上的共享鎖.如果另一個會話已經獲取了待更新記錄上的排他鎖,那麼當前會話將被掛起,直至使用COMMIT或ROLLBACK命令解除這些鎖定,如果另一個會話已經獲取了待修改記錄的表上的共享鎖以及其他記錄上的排他鎖,那麼就不存在任何問題.一個表上的排他鎖會鎖定這個表,但是,如果不需要執行DDL語句,那麼我們就可以不鎖定整個表的默認鎖定機制.
 
提示:
只有在特別請求並且編程人員具有充分理由的情況下,纔可以要求在整個表上放置排他鎖.

 

 
DML鎖與DDL鎖
所有DML語句都至少需要兩種鎖定:受影響記錄上的排他鎖,以及包含受影響記錄的表上的共享鎖.排他鎖能夠防止其他會話干預指定的記錄,而共享鎖則能夠阻止其他會話使用DDL語句修改表的定義.這兩種鎖定會被自動請求.如果某條DML語句在指定記錄上無法獲取所需的排他鎖,那麼這條語句會被掛起直至獲得所需的排他鎖.
執行DDL命令需要使用所涉及對象上的排他鎖.只有在針對指定表的所有DML事務結束,並且記錄上的排他鎖以及表上的共享鎖都被解除之後,我們纔可以獲得執行DDL命令所需的排他鎖,任何DDL語句所需的排他鎖都是被自動請求的.但是,如果無法獲取所需的排他鎖(通常是因爲其他會話已經獲得用於DML語句的共享鎖),那麼DDL語句就會由於錯誤立即終止.
 
爲了更好的說明鎖機制,我們還是看一個世紀的例子吧:
1.       使用SQL*PLUS,作爲用戶SYSTEM連接數據庫.
2.       創建一個表,並且在這個表中插入一條記錄.
>create table t1(c1 number);
       >insert into t1 values(1);
       >commit;
3.再次使用SQL*PLUS並作爲用戶SYSTEM進行連接,從而打開另一個會話.
4.在第一個會話中執行一個DML命令,這個命令會在插入的記錄上放置一個排他鎖,同時還會在創建的表上放置一個共享鎖.
   >update table t1 set c1=2 where c1=1;
5.如下所示,在第二個會話中執行第一條針對新建表的DDL語句.
   >alter table t1 add(c2 date);
   error at line 1:
ora-00054:resource busy and acquire with nowait specified
因爲DDL語句需要表上的排他鎖,而這與DML語句已在表上放置了共享鎖相沖突,所以試圖在表中插入一個列的這條DDL語句會失敗.需要注意的是:在類似情況下,DML語句會等待並不斷進行嘗試,直至獲得其所需的鎖(換句話說就是掛起);而DDL語句則會由於錯誤立即終止.
       6.在第一個會話中,提交當前事務
          >commit;
       7.在第二個會話中,重新執行步驟5.此時,因爲不純在與DDL排他鎖相沖突的DML共享鎖,因此DDL語句將成功的執行.
       8.在第一個會話中 ,鎖定整個表.
        >lock table t1 in exclusive mode;
       9.在第二個會話中,插入一條記錄.此時,這個會話將被掛起.
        >insert into t1 values (1,sysdate);
       10.在第一個會話中,通過執行COMMIT命令解除整個表上的鎖定.需要注意的是,ROLLBACK命令也可以實現相同的目的.
        >commit;
       11.第二個會話會釋放並且現在會完成插入操作.隨後,執行COMMIT命令,終止當前事務斌且解除該記錄上的排他鎖.

關於如何解決死鎖的問題.

1.查哪個過程被鎖
查V$DB_OBJECT_CACHE視圖:


SELECT * FROM V$DB_OBJECT_CACHE WHERE OWNER=''過程的所屬用戶'' AND LOCKS!=''0'';

2. 查是哪一個SID,通過SID可知道是哪個SESSION.
查V$ACCESS視圖:


SELECT * FROM V$ACCESS WHERE OWNER=''過程的所屬用戶'' AND NAME=''剛纔查到的過程名'';

3. 查出SID和SERIAL#
查V$SESSION視圖:


SELECT SID,SERIAL#,PADDR FROM V$SESSION WHERE SID=''剛纔查到的SID''

查V$PROCESS視圖:


SELECT SPID FROM V$PROCESS WHERE ADDR=''剛纔查到的PADDR'';

4. 殺進程
(1).先殺ORACLE進程:


ALTER SYSTEM KILL SESSION ''查出的SID,查出的SERIAL#'';

(2).再殺操作系統進程:


KILL -9 剛纔查出的SPID

ORAKILL 剛纔查出的SID 剛纔查出的SPID
文章出處:DIY部落

 

 

 

 

 

 

 

 

 

 

 

 

關於鎖的解決方案:

 

.net的解決方案

 

大多數據庫自身都有很好的迸發處理機制,程序中你只要用事務處理來保證數據的一致性和完整性即可....

 

MS-SQL Server 使用以下資源鎖模式。

鎖模式 描述
共享 (S) 用於不更改或不更新數據的操作(只讀操作),如 SELECT 語句。
更新 (U) 用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。
排它 (X) 用於數據修改操作,例如 INSERT、UPDATE 或 DELETE。確保不會同時同一資源進行多重更新。
意向鎖 用於建立鎖的層次結構。意向鎖的類型爲:意向共享 (IS)、意向排它 (IX) 以及與意向排它共享 (SIX)。
架構鎖 在執行依賴於表架構的操作時使用。架構鎖的類型爲:架構修改 (Sch-M) 和架構穩定性 (Sch-S)。
大容量更新 (BU) 向表中大容量複製數據並指定了 TABLOCK 提示時使用。

 

 

用事物處理鎖的問題

 

public void ExeSqls(string theSql)
        {
           
using (SqlCommand theCommand2 = new SqlCommand())
            {
                theConn.Open();
                SqlTransaction trans
= theConn.BeginTransaction(IsolationLevel.ReadCommitted);
               
try
                {
                    theCommand2.Connection
= theConn;
                    theCommand2.Transaction
= trans;
                    theCommand2.CommandText
= theSql;
                    theCommand2.ExecuteNonQuery();
                    trans.Commit();
                  
                }
               
catch (Exception ex)
                {
                    trans.Rollback();
                   
throw new ApplicationException(ex.Message);
                }
               
finally
                {
                    theConn.Close();
                }
            }
        }

 

也可以用lock關鍵字來掛起當前線程等

 

lock

{

    ......

}

發佈了56 篇原創文章 · 獲贊 2 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章