1. 程式人生 > >淺談Sql 中的鎖

淺談Sql 中的鎖

轉自:http://blog.csdn.net/abrahamcheng/article/details/6216428

淺談Sql 中的鎖

1.鎖的概念

           Sql server 使用鎖來確保事務的獨立性,鎖可以為某個事務鎖定資源,防止事務間就訪問統一資源的發生衝突,如多個事務同時請求更新某條記,當某個事務開始時就lock住它要更新的記錄,直到該事務結束 (unblock) 釋放該資源, 這樣其他事務在請求更新該記錄時就會被block, 直到佔用該資源的事務結束才有可能unblock.

 2.鎖的模式和相容性

            鎖一般可以分為排他鎖和共享鎖,當需要更新,刪除時使用排他鎖,當僅僅要讀某個資源時使用的是共享鎖。因此排他鎖又稱之為寫鎖,共享鎖又稱之為讀鎖。鎖之間的相容性是指某個資源被加了某種鎖A後能否再加其他鎖B,如果可以則成為鎖A對鎖B是相容的。

相容性

寫鎖

讀鎖

寫鎖

No

No

讀鎖

No

Yes

由上表可見僅共享鎖是相容共享鎖的。

3.可以被鎖的資源型別(鎖的粒度)

      Sql Server 可以鎖定不同的資源型別,或者說鎖的粒度是不同的。 這些資源的型別可以有:RID or key (row), page, object (for example, table), database。 但row是屬於某個page的,page 又是屬於某個block(儲存塊)的 ……, 因此當要鎖(exclusive lock)定一格row時,先要用意向鎖(intent exclusive lock)鎖定該row的上一層粒度page. 同樣讀取某個記錄時在加共享鎖之前也要先給對的的page加共享意向鎖(intent share lock).

Requested Mode

Granted Exclusive (X)

Granted Shared (S)

Granted Intent Exclusive (IX)

Granted Intent Shared (IS)

Grant Request for Exclusive?

No

No

No

No

Grant Request for Shared?

No

Yes

No

Yes

Grant Request for Intent Exclusive?

No

No

Yes

Yes

Grant Request for Intent Shared?

No

Yes

Yes

Yes

這些鎖的粒度一般由Sql server 動態決定,鎖是要消耗資源的,一個簡單的Sql 語句可能會用到成千上萬的鎖。它們也會隨著Sql語句的執行結束而釋放它們所站的資源。

4.和鎖有關比較有幫助的Sql:

檢視所有鎖的資訊:

SELECT -- use * to explore other available attributes

  request_session_id            AS spid,

  resource_type                 AS restype,

  resource_database_id          AS dbid,

  DB_NAME(resource_database_id) AS dbname,

  resource_description          AS res,

  resource_associated_entity_id AS resid,

  request_mode                  AS mode,

  request_status                AS status

FROM sys.dm_tran_locks;

檢視對應的session:

SELECT -- use * to explore

  session_id AS spid,

  connect_time,

  last_read,

  last_write,

  most_recent_sql_handle

FROM sys.dm_exec_connections

WHERE session_id = @spid

檢視session 執行的sql語句:

SELECT session_id, text

FROM sys.dm_exec_connections

  CROSS APPLY sys.dm_exec_sql_text(most_recent_sql_handle) AS ST

WHERE session_id @spid

檢視session的執行帳戶和相關資訊:

SELECT -- use * to explore

  session_id AS spid,

  login_time,

  host_name,

  program_name,

  login_name,

  nt_user_name,

  last_request_start_time,

  last_request_end_time

FROM sys.dm_exec_sessions

WHERE session_id IN(52, 53);

檢視是否有block的session:

SELECT -- use * to explore

  session_id AS spid,

  blocking_session_id,

  command,

  sql_handle,

  database_id,

  wait_type,

  wait_time,

  wait_resource

FROM sys.dm_exec_requests

WHERE blocking_session_id > 0;

設定鎖的超時時間:

SET LOCK_TIMEOUT 5000; 

SET LOCK_TIMEOUT -1; // 該句鎖的超時時間設定成預設時間 

 終止一個session :
   KILL @spid;