锁定

 

锁定

 

一并发控制模型

1 悲观并发控制

2 乐观并发控制

 

二事务控制

 

ACID属性:Atomicity(原子性),Consistency(一致性),Isolation(隔离性),Durability(持续性);

 

三隔离级别

 

Uncommitted Read(未提交读)

Read Committed(已提交读)

Repeatable Read(可重复读)

Snapshot(快照)

Serializable(可串行化)

 

四锁

 

1 概念

锁(lock)保证数据的逻辑一致性;

闩(latch)保证物理一致性;供SQL Server内部使用;

自旋锁(Spinlocks)为互斥而设计的;

闩比用来锁定数据和索引叶子分页的完全锁更加轻量;

自旋锁比闩和锁更加轻量;

 

2 锁的模式

Abbreviation  Lock Mode

S      Shared  

X      Exclusive

U      Update

IS     Intent shared

IU     Intent update

IX     Intent exclusive

SIX    Shared with intent exclusive

SIU    Shared with intent update

UIX    Update with intent exclusive

Sch-S  Schema stability

Sch-M  Schema modification

BU     Bulk update

 

3 锁定的资源

表示资源类型:DATABASEFILEOBJECTPAGEKEYEXTENTRIDAPPLICATIONMETADATAHOBT ALLOCATION_UNIT

 

 

4 查看视图sys.dm_tran_locks

CREATE VIEW DBlocks AS

SELECT request_session_id as spid,

    db_name(resource_database_id) as dbname,

    CASE

   WHEN resource_type = 'OBJECT' THEN

         object_name(resource_associated_entity_id)

      WHEN resource_associated_entity_id = 0 THEN 'n/a'

   ELSE object_name(p.object_id)

    END as entity_name, index_id,

       resource_type as resource,

       resource_description as description,

       request_mode as mode, request_status as status

FROM sys.dm_tran_locks t LEFT JOIN sys.partitions p

   ON p.hobt_id = t.resource_associated_entity_id

WHERE resource_database_id = db_id();

 

 

 

SELECT

   request_session_id,

   resource_type,

   DB_NAME(resource_database_id) AS DatabaseName,

   OBJECT_NAME(resource_associated_entity_id) AS TableName,

   request_mode,

   request_type,

   request_status

FROM sys.dm_tran_locks AS TL

   JOIN sys.all_objects AS AO

   ON TL.resource_associated_entity_id = AO.object_id

WHERE request_type = 'LOCK'

   AND request_status = 'GRANT'

   AND request_mode IN ('X','S')

   AND AO.type = 'U'

   AND resource_type = 'OBJECT'

   AND TL.resource_database_id = DB_ID();

 

5 锁兼容

某个进程正在资源上申请锁,如果该锁可以在一个不同的进程已经占有同已资源上的另一个

锁时被授权,那么称这两个锁是兼容的;如果一个申请资源的锁与另一个当前正在被持有的锁是

不兼容的,那么正在请求的连接就必须等待锁被释放。

 

6 锁升级和禁用锁升级

 

7 锁定提示

SELECT select_list

FROM object [WITH (locking hint)]

 

DELETE [FROM] object [WITH (locking hint)

[WHERE <search conditions>]

 

UDPATE object [WITH (locking hint)

SET <set_clause>

[WHERE <search conditions>]

 

INSERT [INTO] object [WITH (locking hint)

<insert specification>

 

HOLDLOCK

UPDLOCK 可以消除转换死锁

TABLOCK DELETE语句一起使用,能够使SQL Server在行被删除时回收分页(如果在堆上进行删除时

获取了行级锁或者分页锁,这些空间就不会被回收且无法被其它对象使用)

PAGLOCK

TABLOCKX

ROWLOCK

READUNCOMMITTED | REPEATABLEREAD | SERIALIZABLE

READCOMMITTED

READCOMMITTEDLOCK

NOLOCK

READPAST 用在数据表作为队列情况下,与(top 1)语句结合使用

XLOCK 

 

--设定锁超时

SET LOCK_TIMEOUT 5000;

SELECT @@LOCK_TIMEOUT;

 

 

8 锁,阻塞和死锁的区别:

锁是一种基本的并发机制;阻塞是指一个任务被迫等待被另外一个锁住的资源;

死锁是指两个任务彼此互相阻塞;

普通的锁等待并不是一种死锁。当持有锁的进程完成以后,等待的进程就能

够获取锁了。在多用户系统中,锁等待是正常的,预期的和必然的。

 

 

9 等待

()等待两种情况:

许多进程等待同一个资源;阻塞链;

()检测等待

性能计数器:SQLServer:General StatisticsLock Waits );SQLServer:Wait Statistics

DMV视图:sys.dm_os_waiting_tasks sys.dm_tran_locks

sp_who  sp_who2 查看 blk BlkBy

sysprocesses

DBCC INPUTBUFFER

sys.dm_exec_requests

 

--查看持续时间大于秒

SELECT

   WT.session_id AS waiting_session_id,

   WT.waiting_task_address,

   WT.wait_duration_ms,

   WT.wait_type,

   WT.blocking_session_id,

   WT.resource_description

FROM sys.dm_os_waiting_tasks AS WT

WHERE WT.wait_duration_ms > 5000;

 

 

 

--pick out each waiting and granted lock for each given resource

SELECT

   TL1.resource_type,

   DB_NAME(TL1.resource_database_id) AS DatabaseName,

   TL1.resource_associated_entity_id,

   TL1.request_session_id,

   TL1.request_mode,

   TL1.request_status

FROM sys.dm_tran_locks as TL1

   JOIN sys.dm_tran_locks as TL2

   ON TL1.resource_associated_entity_id = TL2.resource_associated_entity_id

   AND TL1.request_status <> TL2.request_status

   AND (TL1.resource_description = TL2.resource_description

   OR (TL1.resource_description IS NULL AND TL2.resource_description IS NULL))

ORDER BY TL1.request_status ASC;

 

 

SELECT

   TL1.resource_type,

   DB_NAME(TL1.resource_database_id) AS DatabaseName,

   CASE TL1.resource_type

      WHEN 'OBJECT' THEN OBJECT_NAME(TL1.resource_associated_entity_id,

         TL1.resource_database_id)

      WHEN 'DATABASE' THEN 'DATABASE'

      ELSE

         CASE

            WHEN TL1.resource_database_id = DB_ID() THEN

                (SELECT OBJECT_NAME(object_id, TL1.resource_database_id)

                 FROM sys.partitions

                 WHERE hobt_id = TL1.resource_associated_entity_id)

            ELSE NULL

         END

   END AS ObjectName,

   TL1.resource_description,

   TL1.request_session_id,

   TL1.request_mode,

   TL1.request_status

FROM sys.dm_tran_locks AS TL1

   JOIN sys.dm_tran_locks AS TL2

   ON TL1.resource_associated_entity_id = TL2.resource_associated_entity_id

WHERE TL1.request_status <> TL2.request_status

   AND (TL1.resource_description = TL2.resource_description

   OR (TL1.resource_description IS NULL

   AND TL2.resource_description IS NULL))

ORDER BY TL1.resource_database_id,

   TL1.resource_associated_entity_id,

   TL1.request_status ASC;

 

 

--Trace

EXEC sp_configure 'show advanced options', 1;

RECONFIGURE;

GO

EXEC sp_configure 'blocked process threshold', 60;

RECONFIGURE;

 

 

--Errors and WarningsBlocked Process Report 事件类指明某个任务已被阻塞,导致超过指定的时间。此事件类不包括系统任务和正在等待未发现死锁的资源的任务。

 

 

 

--SQLDiag

Server>__sp_perf_stats09_Startup.OUT  -- headblockersummary --

 

--查看阻塞任务

SELECT

   WT.session_id AS waiting_session_id,

   DB_NAME(TL.resource_database_id) AS DatabaseName,

   WT.wait_duration_ms,

   WT.waiting_task_address,

   TL.request_mode,

   (SELECT SUBSTRING(ST.text, (ER.statement_start_offset/2) + 1,

      ((CASE ER.statement_end_offset

         WHEN -1 THEN DATALENGTH(ST.text)

         ELSE ER.statement_end_offset

        END - ER.statement_start_offset)/2) + 1)

   FROM sys.dm_exec_requests AS ER

      CROSS APPLY sys.dm_exec_sql_text(ER.sql_handle) AS ST

   WHERE ER.session_id = TL.request_session_id)

      AS waiting_query_text,

   TL.resource_type,

   TL.resource_associated_entity_id,

   WT.wait_type,

   WT.blocking_session_id,

   WT.resource_description AS blocking_resource_description,

   CASE WHEN WT.blocking_session_id > 0 THEN

      (SELECT ST2.text FROM sys.sysprocesses AS SP

             CROSS APPLY sys.dm_exec_sql_text(SP.sql_handle) AS ST2

      WHERE SP.spid = WT.blocking_session_id)

      ELSE NULL

   END AS blocking_query_text

FROM sys.dm_os_waiting_tasks AS WT

   JOIN sys.dm_tran_locks AS TL

   ON WT.resource_address = TL.lock_owner_address

WHERE WT.wait_duration_ms > 5000

   AND WT.session_id > 50;

 

 

 

 

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

--10 死锁

()死锁分类:读/写循环死锁,/写循环死锁,转换死锁;

()检测:

性能计数器:SQLServer:Locks  Number of Deadlocks/Sec

Trace: Lock:Deadlock , Lock:Deadlock Chain

 Deadlock graph event

 DBCC TRACEON (3605, 1222, -1)

 

 

--1 process A:

BEGIN TRAN

UPDATE  Production.Product

    SET ListPrice = ListPrice * 0.9

    WHERE ProductID = 922;

 

--2 process B:

BEGIN TRAN

UPDATE  Purchasing.PurchaseOrderDetail

    SET OrderQty = OrderQty + 200

    WHERE ProductID = 922

    AND PurchaseOrderID = 499;

 

--3 process A:

UPDATE  Purchasing.PurchaseOrderDetail

    SET OrderQty = OrderQty - 200

    WHERE ProductID = 922

    AND PurchaseOrderID = 499;

 

--4 process B:

UPDATE  Production.Product

    SET ListPrice = ListPrice * 0.9

    WHERE ProductID = 922;

   

   

--列出最初锁住资源,导致一连串其他进程被锁住的起始源头

IF EXISTS(SELECT * FROM master.sys.sysprocesses WHERE spid

    IN (SELECT blocked FROM master.sys.sysprocesses)) --确定有进程被其他的进程锁住

    SELECT spid 进程,status 状态, 登入帐号=SUBSTRING(SUSER_SNAME(sid),1,30),

       使用者机器名称=SUBSTRING(hostname,1,12), 是否被锁住=CONVERT(char(3),blocked),

       数据库名称= SUBSTRING(DB_NAME(dbid),1,20),cmd 命令,waittype 等待型态

    FROM master.sys.sysprocesses

    --列出锁住别人(在别的进程中blocked字段出现的值),但自己未被锁住(blocked=0)

    WHERE spid IN (SELECT blocked FROM master.sys.sysprocesses)

    AND blocked=0

ELSE

    SELECT '没有进程被锁住'

 

-- 查看锁的链接关系

select t1.resource_type as [资源锁定类型]

    ,db_name(resource_database_id) as [数据库名]

    ,t1.resource_associated_entity_id as [锁定的对象]

    ,t1.request_mode as [等待者需求的锁定类型]

    ,t1.request_session_id as [等待者sid] 

    ,t2.wait_duration_ms as [等待时间]  

    ,(select text from sys.dm_exec_requests as r 

       cross apply sys.dm_exec_sql_text(r.sql_handle)

       where r.session_id = t1.request_session_id) as [等待者要执行的批次]

    ,(select substring(qt.text,r.statement_start_offset/2+1,

           (case when r.statement_end_offset = -1

           then datalength(qt.text)

           else r.statement_end_offset end - r.statement_start_offset)/2+1)

       from sys.dm_exec_requests as r

       cross apply sys.dm_exec_sql_text(r.sql_handle) as qt

       where r.session_id = t1.request_session_id) as [等待者正要执行的语法]

     ,t2.blocking_session_id as [锁定者sid]

     ,(select text from sys.sysprocesses as p    

       cross apply sys.dm_exec_sql_text(p.sql_handle)

       where p.spid = t2.blocking_session_id) as [锁定者的语法]

    from

    sys.dm_tran_locks as t1,

    sys.dm_os_waiting_tasks as t2

where

    t1.lock_owner_address = t2.resource_address

 

 

 

 

--11 解决死锁方法:

Determine whether a short-term or long-term solution is required.

Isolate the deadlocking code and reproduce it in a test setting.

Check the granularity and amount of locking in the deadlocks.

Check for missing indexes.

Shorten the transactions.

Retry the transaction if it is a deadlock victim.

Lower the deadlock priority of one process.

Use bound connections.

 

 

 

posted @ 2008-11-03 11:48  深潭  阅读(644)  评论(0编辑  收藏  举报