--阻塞
/***********************************************************************************************************************
阻塞:其中一個事務(wù)阻塞,其它事務(wù)等待對方釋放它們的鎖,同時會導(dǎo)致死鎖問題。
--生成測試表Ta
if not object_id('Ta') is null
drop table Ta
go
create table Ta(ID int Primary key,Col1 int,Col2 nvarchar(10))
insert Ta
select 1,101,'A' union all
select 2,102,'B' union all
select 3,103,'C'
go
生成數(shù)據(jù):
/*
表Ta
ID Col1 Col2
----------- ----------- ----------
1 101 A
2 102 B
3 103 C
(3 行受影響)
*/
將處理阻塞減到最少:
1、事務(wù)要盡量短
2、不要在事務(wù)中請求用戶輸入
3、在讀數(shù)據(jù)考慮便用行版本管理
4、在事務(wù)中盡量訪問最少量的數(shù)據(jù)
5、盡可能地使用低的事務(wù)隔離級別
go
阻塞1(事務(wù)):
--測試單表
-----------------------------連接窗口1(update\insert\delete)----------------------
begin tran
--update
update ta set col2='BB' where ID=2
--或insert
begin tran
insert Ta values(4,104,'D')
--或delete
begin tran
delete ta where ID=1
--rollback tran
------------------------------------------連接窗口2--------------------------------
begin tran
select * from ta
--rollback tran
--------------分析-----------------------
select
request_session_id as spid,
resource_type,
db_name(resource_database_id) as dbName,
resource_description,
resource_associated_entity_id,
request_mode as mode,
request_status as Status
from
sys.dm_tran_locks
/*
spid resource_type dbName resource_description resource_associated_entity_id mode Status
----------- ------------- ------ -------------------- ----------------------------- ----- ------
55 DATABASE Test 0 S GRANT NULL
54 DATABASE Test 0 S GRANT NULL
53 DATABASE Test 0 S GRANT NULL
55 PAGE Test 1:201 72057594040483840 IS GRANT
54 PAGE Test 1:201 72057594040483840 IX GRANT
55 OBJECT Test 1774629365 IS GRANT NULL
54 OBJECT Test 1774629365 IX GRANT NULL
54 KEY Test (020068e8b274) 72057594040483840 X GRANT --(spID:54請求了排它鎖)
55 KEY Test (020068e8b274) 72057594040483840 S WAIT --(spID:55共享鎖+等待狀態(tài))
(9 行受影響)
*/
--查連接住信息(spid:54、55)
select connect_time,last_read,last_write,most_recent_sql_handle
from sys.dm_exec_connections where session_id in(54,55)
--查看會話信息
select login_time,host_name,program_name,login_name,last_request_start_time,last_request_end_time
from sys.dm_exec_sessions where session_id in(54,55)
--查看阻塞正在執(zhí)行的請求
select
session_id,blocking_session_id,wait_type,wait_time,wait_resource
from
sys.dm_exec_requests
where
blocking_session_id>0--正在阻塞請求的會話的 ID。如果此列是 NULL,則不會阻塞請求
--查看正在執(zhí)行的SQL語句
select
a.session_id,sql.text,a.most_recent_sql_handle
from
sys.dm_exec_connections a
cross apply
sys.dm_exec_sql_text(a.most_recent_sql_handle) as SQL --也可用函數(shù)fn_get_sql通過most_recent_sql_handle得到執(zhí)行語句
where
a.Session_id in(54,55)
/*
session_id text
----------- -----------------------------------------------
54 begin tran update ta set col2='BB' where ID=2
55 begin tran select * from ta
*/
處理方法:
--連接窗口2
begin tran
select * from ta with (nolock)--用nolock:業(yè)務(wù)數(shù)據(jù)不斷變化中,如銷售查看當(dāng)月時可用。
阻塞2(索引):
-----------------------連接窗口1
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE --針對會話設(shè)置了 TRANSACTION ISOLATION LEVEL
begin tran
update ta set col2='BB' where COl1=102
--rollback tran
------------------------連接窗口2
insert into ta(ID,Col1,Col2) values(5,105,'E')
處理方法:
create index IX_Ta_Col1 on Ta(Col1)--用COl1列上創(chuàng)索引,當(dāng)更新時條件:COl1=102會用到索引IX_Ta_Col1上得到一個排它鍵的范圍鎖
阻塞3(會話設(shè)置):
-------------------------------連接窗口1
begin tran
--update
update ta set col2='BB' where ID=2
select col2 from ta where ID=2
--rollback tran
--------------------------------連接窗口2
SET TRANSACTION ISOLATION LEVEL READ COMMITTED --設(shè)置會話已提交讀:指定語句不能讀取已由其他事務(wù)修改但尚未提交的數(shù)據(jù)
begin tran
select * from ta
處理方法:
--------------------------------連接窗口2(善用會話設(shè)置:業(yè)務(wù)數(shù)據(jù)不斷變化中,如銷售查看當(dāng)月時可用)
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED --設(shè)置會話未提交讀:指定語句可以讀取已由其他事務(wù)修改但尚未提交的行
begin tran
select * from ta