1. DB2資料庫發生死鎖了怎麼辦
先定位一下是哪個程序句柄導致的死鎖。方法一、查看db2diag.log文件找到DeadLockorLocktimeout死鎖或鎖超時信息db2forceapplication(句柄ID)直接結束進程即可。方法二、DB2快照信息1、看一下DB2快照信息可以得到類似信息:資料庫鎖定快照資料庫名稱=SAMPLE資料庫路徑=D:\IBM\DB2\NODE0000\SQL00001\輸入資料庫別名=SAMPLE掛起的鎖定=8當前已連接的應用程序=2當前正等待鎖定的代理程序數=1應用程序句柄=54應用程序標識=*LOCAL.DB2.140304192925序號=00001應用程序名=db2bp.exeCONNECT授權標識=DB2ADMIN應用程序狀態=鎖定等待應用程序代碼頁=1208掛起的鎖定=4總計等待時間(毫秒)=247867鎖定列表鎖定名稱=0x5359534C564C3031DDECEF2841鎖定屬性=0x00000000發行版標志=0x40000000鎖定計數=1掛起計數=0鎖定對象名=2312對象類型=行表空間名=IBMDB2SAMPLEREL表模式=DB2ADMIN表名=TEST方式=IX查看鎖定的詳細信息:----(1728是句柄ID)3、觀察命令db2listapplications的輸出查看應用程序的狀態是否有鎖定等待(Lock-wait)狀態出現。執行命令;4、db2forceapplication(句柄ID)直接結束進程即可。
死鎖主要表現以下幾種情況:
表現一:
一個用戶A 訪問表A(鎖住了表A),然後又訪問表B
另一個用戶B 訪問表B(鎖住了表B),然後企圖訪問表A
這時用戶A由於用戶B已經鎖住表B,它必須等待用戶B釋放表B,才能繼續,好了他老人家就只好老老實實在這等了
同樣用戶B要等用戶A釋放表A才能繼續這就死鎖了
解決方法:
這種死鎖是由於你的程序的BUG產生的,除了調整你的程序的邏輯別無他法
仔細分析你程序的邏輯,
1:盡量避免同時鎖定兩個資源
2: 必須同時鎖定兩個資源時,要保證在任何時刻都應該按照相同的順序來鎖定資源.
表現二:
用戶A讀一條紀錄,然後修改該條紀錄
這是用戶B修改該條紀錄
這里用戶A的事務里鎖的性質由共享鎖企圖上升到獨占鎖(for update),而用戶B里的獨占鎖由於A有共享鎖存在所以必須等A釋
放掉共享鎖,而A由於B的獨占鎖而無法上升的獨占鎖也就不可能釋放共享鎖,於是出現了死鎖。
這種死鎖比較隱蔽,但其實在稍大點的項目中經常發生。
解決方法:
讓用戶A的事務(即先讀後寫類型的操作),在select 時就是用Update lock
語法如下:
select * from table1 with(updlock) where ....
如果真的table被鎖住了,可以通過下面的方法來解鎖:
Sql server企業管理器->對應的資料庫->管理->當前活動->鎖/進程ID
將對應的被鎖住的進程關閉。
還有一種方法,就是在你不知道究竟是哪張表被鎖,由何種原因被鎖,可以重新啟動資料庫來解決,但不保證下次又被鎖住,因為還沒有找到問題的根本原因。
要避免鎖表,在操作資料庫最好不要用獨占方式。
3. 多個程序訪問一個資料庫出現死鎖,怎麼處理
多個程序訪問一個資料庫出現死鎖,你可以這么處理:
增加電腦整體性能配置,主板、網路、CPU/內存、電源都要好一些;
一些不是很重要的、可以設置延遲連接;
定時對資料庫進行維護,優化;
程序也需要維護穩定,管理員工對程序的使用效率。
4. 資料庫死鎖的死鎖原因
一般情況只發生鎖超時,就是一個進程需要訪問資料庫表或者欄位的時候,另外一個程序正在執行帶鎖的訪問(比如修改數據),那麼這個進程就會等待,當等了很久鎖還沒有解除的話就會鎖超時,報告一個系統錯誤,拒絕執行相應的SQL操作。
發生死鎖的情況比較少,比如一個進程需要訪問兩個資源(資料庫表或者欄位),當獲取一個資源的時候進程就對它執行鎖定,然後等待下一個資源空閑,這時候如果另外一個進程也需要兩個資源,而已經獲得並鎖定了第二個資源,那麼就會死鎖,因為當前進程鎖定第一個資源等待第二個資源,而另外一個進程鎖定了第二個資源等待第一個資源,兩個進程都永遠得不到滿足。
資料庫死鎖的解決方案。
死鎖的預防和解除:
理解了死鎖的原因,尤其是產生死鎖的四個必要條件,就可以最大可能地避免、預防和解除死鎖。所以,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確定資源的合理分配演算法,避免進程永久占據系統資源。此外,也要防止進程在處於等待狀態的情況下佔用資源,在系統運行過程中,對進程發出的每一個系統能夠滿足的資源申請進行動態檢查,並根據檢查結果決定是否分配資源,若分配後系統可能發生死鎖,則不予分配,否則予以分配 。因此,對資源的分配要給予合理的規劃。
如何將死鎖減至最少
雖然不能完全避免死鎖,但可以使死鎖的數量減至最少。將死鎖減至最少可以增加事務的吞吐量並減少系統開銷,因為只有很少的事務回滾,而回滾會取消事務執行的所有工作。由於死鎖時回滾而由應用程序重新提交。
下列方法有助於最大限度地降低死鎖:
(1)按同一順序訪問對象。
(2)避免事務中的用戶交互。
(3)保持事務簡短並在一個批處理中。
(4)使用低隔離級別。
(5)使用綁定連接。
按同一順序訪問對象
如果所有並發事務按同一順序訪問對象,則發生死鎖的可能性會降低。例如,如果兩個並發事務獲得 Supplier 表上的鎖,然後獲得 Part 表上的鎖,則在其中一個事務完成之前,另一個事務被阻塞在 Supplier 表上。第一個事務提交或回滾後,第二個事務繼續進行。不發生死鎖。將存儲過程用於所有的數據修改可以標准化訪問對象的順序。
避免事務中的用戶交互
避免編寫包含用戶交互的事務,因為運行沒有用戶交互的批處理的速度要遠遠快於用戶手動響應查詢的速度,例如答復應用程序請求參數的提示。例如,如果事務正在等待用戶輸入,而用戶去吃午餐了或者甚至回家過周末了,則用戶將此事務掛起使之不能完成。這樣將降低系統的吞吐量,因為事務持有的任何鎖只有在事務提交或回滾時才會釋放。即使不出現死鎖的情況,訪問同一資源的其它事務也會被阻塞,等待該事務完成。
保持事務簡短並在一個批處理中
在同一資料庫中並發執行多個需要長時間運行的事務時通常發生死鎖。事務運行時間越長,其持有排它鎖或更新鎖的時間也就越長,從而堵塞了其它活動並可能導致死鎖。
保持事務在一個批處理中,可以最小化事務的網路通信往返量,減少完成事務可能的延遲並釋放鎖。
使用低隔離級別
確定事務是否能在更低的隔離級別上運行。執行提交讀允許事務讀取另一個事務已讀取(未修改)的數據,而不必等待第一個事務完成。使用較低的隔離級別(例如提交讀)而不使用較高的隔離級別(例如可串列讀)可以縮短持有共享鎖的時間,從而降低了鎖定爭奪。
使用綁定連接
使用綁定連接使同一應用程序所打開的兩個或多個連接可以相互合作。次級連接所獲得的任何鎖可以象由主連接獲得的鎖那樣持有,反之亦然,因此不會相互阻塞。
5. 資料庫中死鎖是什麼產生的
資料庫操作的死鎖是不可避免的,本文並不打算討論死鎖如何產生,重點在於解決死鎖,通過SQL
Server
2005,
現在似乎有了一種新的解決辦法。
將下面的SQL語句放在兩個不同的連接裡面,並且在5秒內同時執行,將會發生死鎖。
use
Northwind
begin
tran
insert
into
Orders(CustomerId)
values(@#ALFKI@#)
waitfor
delay
@#00:00:05@#
select
*
from
Orders
where
CustomerId
=
@#ALFKI@#
commit
print
@#end
tran@#
SQL
Server對付死鎖的辦法是犧牲掉其中的一個,拋出異常,並且回滾事務。在SQL
Server
2000,語句一旦發生異常,T-SQL將不會繼續運行,上面被犧牲的連接中,
print
@#end
tran@#語句將不會被運行,所以我們很難在SQL
Server
2000的T-SQL中對死鎖進行進一步的處理。
現在不同了,SQL
Server
2005可以在T-SQL中對異常進行捕獲,這樣就給我們提供了一條處理死鎖的途徑:
下面利用的try
...
catch來解決死鎖。
SET
XACT_ABORT
ON
declare
@r
int
set
@r
=
1
while
@r
<=
3
begin
begin
tran
begin
try
insert
into
Orders(CustomerId)
values(@#ALFKI@#)
waitfor
delay
@#00:00:05@#
select
*
from
Orders
where
CustomerId
=
@#ALFKI@#
commit
break
end
try
begin
catch
rollback
waitfor
delay
@#00:00:03@#
set
@r
=
@r
+
1
continue
end
catch
end
解決方法當然就是重試,但捕獲錯誤是前提。rollback後面的waitfor不可少,發生沖突後需要等待一段時間,@retry數目可以調整以應付不同的要求。
但是現在又面臨一個新的問題:
錯誤被掩蓋了,一但問題發生並且超過3次,異常卻不會被拋出。SQL
Server
2005
有一個RaiseError語句,可以拋出異常,但卻不能直接拋出原來的異常,所以需要重新定義發生的錯誤,現在,解決方案變成了這樣:
declare
@r
int
set
@r
=
1
while
@r
<=
3
begin
begin
tran
begin
try
insert
into
Orders(CustomerId)
values(@#ALFKI@#)
waitfor
delay
@#00:00:05@#
select
*
from
Orders
where
CustomerId
=
@#ALFKI@#
commit
break
end
try
begin
catch
rollback
waitfor
delay
@#00:00:03@#
set
@r
=
@r
+
1
continue
end
catch
end
if
ERROR_NUMBER()
<>
0
begin
declare
@ErrorMessage
nvarchar(4000);
declare
@ErrorSeverity
int;
declare
@ErrorState
int;
select
@ErrorMessage
=
ERROR_MESSAGE(),
@ErrorSeverity
=
ERROR_SEVERITY(),
@ErrorState
=
ERROR_STATE();
raiserror
(@ErrorMessage,
@ErrorSeverity,
@ErrorState
);
end
6. 資料庫死鎖怎麼產生,怎樣能解決
資料庫操作的死鎖是不可避免的,本文並不打算討論死鎖如何產生,重點在於解決死鎖,通過SQL Server 2005, 現在似乎有了一種新的解決辦法。
將下面的SQL語句放在兩個不同的連接裡面,並且在5秒內同時執行,將會發生死鎖。
use Northwind
begin tran
insert into Orders(CustomerId) values(@#ALFKI@#)
waitfor delay @#00:00:05@#
select * from Orders where CustomerId = @#ALFKI@#
commit
print @#end tran@#
SQL Server對付死鎖的辦法是犧牲掉其中的一個,拋出異常,並且回滾事務。在SQL Server 2000,語句一旦發生異常,T-SQL將不會繼續運行,上面被犧牲的連接中, print @#end tran@#語句將不會被運行,所以我們很難在SQL Server 2000的T-SQL中對死鎖進行進一步的處理。
現在不同了,SQL Server 2005可以在T-SQL中對異常進行捕獲,這樣就給我們提供了一條處理死鎖的途徑:
下面利用的try ... catch來解決死鎖。
SET XACT_ABORT ON
declare @r int
set @r = 1
while @r <= 3
begin
begin tran
begin try
insert into Orders(CustomerId) values(@#ALFKI@#)
waitfor delay @#00:00:05@#
select * from Orders where CustomerId = @#ALFKI@#
commit
break
end try
begin catch
rollback
waitfor delay @#00:00:03@#
set @r = @r + 1
continue
end catch
end
解決方法當然就是重試,但捕獲錯誤是前提。rollback後面的waitfor不可少,發生沖突後需要等待一段時間,@retry數目可以調整以應付不同的要求。
但是現在又面臨一個新的問題: 錯誤被掩蓋了,一但問題發生並且超過3次,異常卻不會被拋出。SQL Server 2005 有一個RaiseError語句,可以拋出異常,但卻不能直接拋出原來的異常,所以需要重新定義發生的錯誤,現在,解決方案變成了這樣:
declare @r int
set @r = 1
while @r <= 3
begin
begin tran
begin try
insert into Orders(CustomerId) values(@#ALFKI@#)
waitfor delay @#00:00:05@#
select * from Orders where CustomerId = @#ALFKI@#
commit
break
end try
begin catch
rollback
waitfor delay @#00:00:03@#
set @r = @r + 1
continue
end catch
end
if ERROR_NUMBER() <> 0
begin
declare @ErrorMessage nvarchar(4000);
declare @ErrorSeverity int;
declare @ErrorState int;
select
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
raiserror (@ErrorMessage,
@ErrorSeverity,
@ErrorState
);
end
我希望將來SQL Server 2005能夠直接拋出原有異常,比如提供一個無參數的RaiseError。
因此方案有點臃腫,但將死鎖問題封裝到T-SQL中有助於明確職責,提高高層系統的清晰度。現在,對於DataAccess的代碼,或許再也不需要考慮死鎖問題了。
7. 資料庫中解決死鎖的常用方法有什麼
1、要求每個事務一次就將所有要使用的數據全部加鎖,否則不能執行。
2、採用按序加鎖法.預先規定一個封鎖順序,所有的事務都必須按這個順序對數據執行封鎖。
3、不採取任何措施來預防死鎖的發生,而是周期性地檢查系統中是否有死鎖.如果發現死鎖就設法解除。