标签:
006_锁
--通过dmv来查看当前数据库中的锁定和阻塞的详细信息(sys.dm_tran_locks)***********************************************
select
str(request_session_id,4,1) spid, --当前拥有该请求的会话 ID。
db_name(resource_database_id) db_name,
case when resource_database_id=DB_ID() and resource_type=‘OBJECT‘
THEN CONVERT(nvarchar(20),object_name(resource_associated_entity_id))
else CONVERT(nvarchar(20),resource_associated_entity_id)
end object, --数据库中与资源相关联的实体的 ID。
CONVERT(nvarchar(20),resource_type) restr_type, --表示资源类型
CONVERT(nvarchar(20),request_type) req_type, --请求类型
CONVERT(nvarchar(20),request_mode) req_mod, --请求的模式
CONVERT(nvarchar(20),request_status) status --该请求的当前状态
from
sys.dm_tran_locks
order by
request_session_id, 3 desc
--关于【sys.dm_tran_locks】详细注释***********************************************
select
resource_type --表示资源类型。该值可以是下列值之一:DATABASE、FILE、OBJECT、PAGE、KEY、EXTENT、RID、APPLICATION、METADATA、HOBT 或 ALLOCATION_UNIT。
,resource_subtype --子类型
,resource_database_id --数据库id,通过 DB_NAME(resource_database_id) 获得数据库名称
,resource_associated_entity_id --数据库中与资源相关联的实体的 ID。该值可以是对象 ID、Hobt ID 或分配单元 ID,具体视资源类型而定。
,request_mode --请求的模式。对于已授予的请求,为已授予模式;对于等待请求,为正在请求的模式。
,request_type --请求类型。该值为 LOCK。
,request_status --该请求的当前状态。可能值为 GRANTED、CONVERT 或 WAIT。
,request_reference_count --返回同一请求程序已请求该资源的近似次数。
,request_lifetime --无用
,request_session_id --当前拥有该请求的会话 ID。
,request_owner_type /*
拥有请求的实体类型。锁管理器请求可由各种实体所拥有。可能的值有:
TRANSACTION = 请求由事务所有。
CURSOR = 请求由游标所有。
SESSION = 请求由用户会话所有。
SHARED_TRANSACTION_WORKSPACE = 请求由事务工作区的共享部分所有。
EXCLUSIVE_TRANSACTION_WORKSPACE = 请求由事务工作区的排他部分所有。
*/
from
sys.dm_tran_locks
--查看哪个进程阻塞了哪几个进程***********************************************
--方法一:查询【sys.dm_os_waiting_tasks】
select
waiting_task_address --等待任务的地址。
,session_id --与任务关联的会话的 ID。【【【被阻塞方ID】】】
,wait_duration_ms -- 此等待类型的总等待时间(毫秒)。此时间包含 signal_wait_time。【【【阻塞时间】】】
,wait_type --等待类型的名称。
,resource_address --任务等待的资源的地址。
,blocking_task_address --当前持有此资源的任务。
,blocking_session_id /*【【【阻塞主动方ID】】】
正在阻塞请求的会话的 ID。如果此列为 NULL,则表示请求未被阻塞,或锁定会话的会话信息不可用(或无法进行标识)。
-2 = 阻塞资源由孤立的分布式事务拥有。
-3 = 阻塞资源由延迟的恢复事务拥有。
-4 = 由于内部闩锁状态转换而无法确定阻塞闩锁所有者的会话 ID。
*/
,blocking_exec_context_id -- 正在阻塞的任务的执行上下文 ID。
from
sys.dm_os_waiting_tasks
--------------------------------------------------
--方法二:执行【sp_lock】
exec sp_lock
--------------------------------------------------
--解决进城阻塞的方法***********************************************
/*
阻塞实例:
窗口一:
begin tran
update ##test_liwz set b=‘5‘
此时执行,故意不提交或回滚这个事物
窗口二:
select * from ##test_liwz
此时执行,就会发生阻塞
*/
----------------------------------------------
--方法一:
--加上 with (nolock),此时不考虑表的锁定状态,但不适用于insert,update,delete
select * from ##test_liwz with (nolock)
----------------------------------------------
--方法二:
--设置事务隔离级别为 dirty read【脏读】,这样做可以使查询不用请求共享锁,即永远不会和其他事物发生冲突
set transaction isolation level read uncommited
select * from ##test_liwz
----------------------------------------------
--方法三:
--使用 set lock_timeout 3000(3秒未成功,则抛出超时等候的错误 1222)(@@lock_timeout在其他会话中会默认为-1)
select @@LOCK_TIMEOUT -- -1
set lock_timeout 3000
select * from ##test_liwz --(3秒后报错)
----------------------------------------------
--方法四:杀掉阻塞进程
--查询哪个进程阻塞了哪个进程
select
blocking_session_id --【【【阻塞主动方ID】】】
,session_id --与任务关联的会话的 ID。【【【被阻塞方ID】】】
,wait_duration_ms -- 此等待类型的总等待时间(毫秒)。此时间包含 signal_wait_time。【【【阻塞时间】】】
from
sys.dm_os_waiting_tasks
--杀掉进程【blocking_session_id】
kill 64
--阻塞进程被杀后,@@trancount=0,事物回滚,临时表也被删除
----------------------------------------------
--【set transaction isolation level】隔离级别***********************************************
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED --指定语句可以读取已由其他事务修改但尚未提交的行。
| READ COMMITTED --指定语句不能读取已由其他事务修改但尚未提交的数据。
| REPEATABLE READ --指定语句不能读取已由其他事务修改但尚未提交的行,并且指定,其他任何事务都不能在当前事务完成之前修改由当前事务读取的数据。
| SNAPSHOT --指定事务中任何语句读取的数据都将是在事务开始时便存在的数据的事务上一致的版本。事务只能识别在其开始之前提交的数据修改。在当前事务中执行的语句将看不到在当前事务开始以后由其他事务所做的数据修改。其效果就好像事务中的语句获得了已提交数据的快照,因为该数据在事务开始时就存在。
| SERIALIZABLE
/*
语句不能读取已由其他事务修改但尚未提交的数据。
任何其他事务都不能在当前事务完成之前修改由当前事务读取的数据。
在当前事务完成之前,其他事务不能使用当前事务中任何语句读取的键值插入新行。
*/
}
[ ; ]
---------------------------------------------------------------
/*
总结:
尽量将查询写到事物外;
事物内尽量用存储过程代替sql语句
@@lock_timeout的值默认为-1,对它的设置只是在当前会话有效
一个锁为8k,分为:行锁、叶锁、表锁。小粒度锁太多时,内存不够时,低粒度锁会向高粒度锁升级。
*/
标签:
原文地址:http://www.cnblogs.com/heibaitan/p/4284978.html