zoukankan
html css js c++ java
数据库阻塞分析死锁并处理
--
死鎖
/**/
/*
*****************************************************************************************************************************************************
死鎖指兩個以上事務相互阻塞相互等待對方釋放它們的鎖,SQL Server會通過回滾其中一個事務並返回一個錯誤來自已解決阻塞問題,讓其他事務完成它們的工作。
整理人:中国风(Roy)
日期:2008.07.20
*****************************************************************************************************************************************************
*/
set
nocount
on
;
if
object_id
(
'
T1
'
)
is
not
null
drop
table
T1
go
create
table
T1(ID
int
primary
key
,Col1
int
,Col2
nvarchar
(
20
))
insert
T1
select
1
,
101
,
'
A
'
insert
T1
select
2
,
102
,
'
B
'
insert
T1
select
3
,
103
,
'
C
'
go
if
object_id
(
'
T2
'
)
is
not
null
drop
table
T2
go
create
table
T2(ID
int
primary
key
,Col1
int
,Col2
nvarchar
(
20
))
insert
T2
select
1
,
201
,
'
X
'
insert
T2
select
2
,
202
,
'
Y
'
insert
T2
select
3
,
203
,
'
Z
'
go
生成表數據:
/**/
/*
T1:
ID Col1 Col2
----------- ----------- --------------------
1 101 A
2 101 B
3 101 C
T2:
ID Col1 Col2
----------- ----------- --------------------
1 201 X
2 201 Y
3 201 Z
*/
防止死鎖:
1
、 最少化阻塞。阻塞越少,發生死鎖機會越少
2
、 在事務中按順序訪問表(以上例子:死鎖2)
3
、 在錯誤處理程式中檢查錯誤1205並在錯誤發生時重新提交事務
4
、 在錯誤處理程式中加一個過程將錯誤的詳細寫入日誌
5
、 索引的合理使用(以上例子:死鎖1、死鎖3)
當發生死鎖時,事務自動提交,可通過日誌來監視死鎖
死鎖1(索引):
--
連接窗口1
--
1步:
begin
tran
update
t1
set
col2
=
col2
+
'
A
'
where
col1
=
101
--
3步:
select
*
from
t2
where
col1
=
201
commit
tran
--
連接窗口2
--
2步:
begin
tran
update
t2
set
col2
=
col2
+
'
B
'
where
col1
=
203
--
4步:
select
*
from
t1
where
col1
=
103
commit
tran
--
連接窗口1:收到死鎖錯誤,連接窗口2得到結果:
/**/
/*
訊息 1205,層級 13,狀態 51,行 3
交易 (處理序識別碼 53) 在 鎖定 資源上被另一個處理序鎖死並已被選擇作為死結的犧牲者。請重新執行該交易。
*/
--
連接窗口2:得到結果
/**/
/*
----------- ----------- --------------------
3 103 C
*/
處理方法:
--
在t1、t2表的col1條件列建索引
create
index
IX_t1_col1
on
t1(col1)
create
index
IX_t2_col1
on
t2(col1)
go
--
連接窗口1
--
1步:
begin
tran
update
t1
set
col2
=
col2
+
'
A
'
where
col1
=
101
--
3步:
select
*
from
t2
with
(
index
=
IX_t2_col1)
where
col1
=
201
--
因表數據少,只能指定索引提示才能確保SQL Server使用索引
commit
tran
--
連接窗口2
--
2步:
begin
tran
update
t2
set
col2
=
col2
+
'
B
'
where
col1
=
203
--
4步:
select
*
from
t1
with
(
index
=
IX_t1_col1)
where
col1
=
103
--
因表數據少,只能指定索引提示才能確保SQL Server使用索引
commit
tran
--
連接窗口1:
/**/
/*
ID Col1 Col2
----------- ----------- --------------------
1 201 X
(1 個資料列受到影響)
*/
--
連接窗口2
/**/
/*
ID Col1 Col2
----------- ----------- --------------------
3 103 C
(1 個資料列受到影響)
*/
死鎖2(訪問表順序):
--
連接窗口1:
--
1步:
begin
tran
update
t1
set
col1
=
col1
+
1
where
ID
=
1
--
3步:
select
col1
from
t2
where
ID
=
1
commit
tran
--
連接窗口2:
--
2步:
begin
tran
update
t2
set
col1
=
col1
+
1
where
ID
=
1
--
4步
select
col1
from
t1
where
ID
=
1
commit
tran
--
連接窗口1:
/**/
/*
col1
-----------
201
(1 個資料列受到影響)
*/
--
連接窗口2:
/**/
/*
col1
-----------
訊息 1205,層級 13,狀態 51,行 1
交易 (處理序識別碼 54) 在 鎖定 資源上被另一個處理序鎖死並已被選擇作為死結的犧牲者。請重新執行該交易。
*/
處理方法:
--
改變訪問表的順序
--
連接窗口1:
--
1步:
begin
tran
update
t1
set
col1
=
col1
+
1
where
ID
=
1
--
3步:
select
col1
from
t2
where
ID
=
1
commit
tran
--
連接窗口2:
--
2步:
begin
tran
select
col1
from
t1
where
ID
=
1
--
會等待連接窗口1提交
--
4步
update
t2
set
col1
=
col1
+
1
where
ID
=
1
commit
tran
死鎖3(單表):
--
連接窗口1:
while
1
=
1
update
T1
set
col1
=
203
-
col1
where
ID
=
2
--
連接窗口2:
declare
@i
nvarchar
(
20
)
while
1
=
1
set
@i
=
(
select
col2
from
T1
with
(
index
=
IX_t1_col1)
where
Col1
=
102
);
--
因表數據少,只能指定索引提示才能確保SQL Server使用索引
--
連接窗口1
/**/
/*
訊息 1205,層級 13,狀態 51,行 4
交易 (處理序識別碼 53) 在 鎖定 資源上被另一個處理序鎖死並已被選擇作為死結的犧牲者。請重新執行該交易。
*/
處理方法:
1
、刪除col1上的非聚集索引,這樣影響SELECT速度,不可取.
drop
index
IX_t1_col1
on
t1
2
、建一個覆蓋索引
A、
drop
index
IX_t1_col1
on
t1
B、
create
index
IX_t1_col1_col2
on
t1(col1,col2)
通過SQL Server Profiler查死鎖信息:
啟動SQL Server Profiler——連接實例——事件選取範圍——顯示所有事件
選擇項:
TSQL——SQL:StmtStarting
Locks——Deadlock graph(這是SQL2005新增事件,生成包含死鎖信息的xml值)
——Lock:DeadlockChain 死鎖鏈中的進程產生該事件,可標識死鎖進程的ID並跟蹤操作
——Lock:Deadlock 該事件發生了死鎖
查看全文
相关阅读:
JAVA 程序pending 数据库锁
圆形相遇问题
DROP TABLE
sed 删除
JVM程序计数器
《神奇的数学》颠覆你对数学的初始感觉
error "OPatch cannot find a valid oraInst.loc file to locate Central Inventory
【linux】提醒"libc.so.6: version `GLIBC_2.14' not found"系统的glibc版本太低
Linux 常用命令随笔(一)
国际结算业务--国际结算中的票据
原文地址:https://www.cnblogs.com/moon25/p/1248806.html
最新文章
SQL SERVER 事务和锁
[转].Net连接池超时注意事项
Jquery DataTable基本使用
Jquery调用ajax参数说明
Css+JS模拟实现可编辑的表格
依赖注入:Ninject学习笔记
js 控制输入文字个数(换行不算)
js 控制输入文字的字数
HttpWebRequest、HttpWebResponse获取网页
【常用配置】——WPS文字常用快捷键大全【史上最全面】转
热门文章
【linux】——一个小程序
【LINUX】——linux如何使用Python创建一个web服务
【LINUX】——FreeBSD中的一些常规配置
【LINUX】——gvim中如何配置字体和背景
【驱动】——seq_file使用指南
【驱动】——字符设备驱动程序
Oracle Database CHECK NUMBER For tables/views/triggers/function/procedure
Different between sqlplus and sqldeveloper
LUN Logical Unit Number
failover机制
Copyright © 2011-2022 走看看