一、死鎖原理
a、根據操作系統中的定義:死鎖是指在一組進程中的各個進程均占有不會釋放的資源,但因互相申請被其他進程所站用不會釋放的資源而處於的一種永久等待狀態。
二、死鎖的四個必要條件:
a、互斥條件(Mutual exclusion):資源不能被共享,只能由一個進程使用。
b、請求與保持條件(Hold and wait):已經得到資源的進程可以再次申請新的資源。
c、非剝奪條件(No pre-emption):已經分配的資源不能從相應的進程中被強制地剝奪。
d、循環等待條件(Circular wait):系統中若干進程組成環路,該環路中每個進程都在等待相鄰進程正占用的資源。
三、避免死鎖
a、按同一順序訪問對象。
b、避免事務中的用戶交互。
c、保持事務簡短並處於一個批處理中。
d、使用較低的隔離級別。
四、查看死鎖例句
開兩個查詢窗口,分別執行下面兩段sql
BEGIN tran
UPDATE a SET dd=dd+1
WaitFor Delay '00:01:00';
SELECT * FROM B
ROLLBACK tran
BEGIN tran
UPDATE B SET age=age+1
WaitFor Delay '00:01:00';
SELECT * FROM A
ROLLBACK tran
五、針對上面語句出現死鎖情況的解決方法
a、根據上面提到的按同一順序訪問對象(調換一下update跟select 執行順序)
BEGIN tran
SELECT * FROM A --將select語句放在前,update語句放在后
WaitFor Delay '00:00:30';
UPDATE B SET age=age+1
ROLLBACK tran
b、在SELECT語句加With(NoLock),加With(NoLock)可能會導致臟讀。
BEGIN tran
UPDATE B SET age=age+1
WaitFor Delay '00:00:10';
SELECT * FROM A WITH(NOLOCK) --select語句上加上with(NOLOCK),有效的避免了死鎖
ROLLBACK tran
還是示例一中的語句,只是加上了WITH(NOLOCK)
BEGIN tran
UPDATE a SET dd=dd+1
WaitFor Delay '00:00:10';
SELECT * FROM B WITH(NOLOCK)
ROLLBACK tran
結果:
c、在sql語句前加上SET LOCK_TIMEOUT,數據默認LOCK_TIMEOUT時間是10分鍾
BEGIN tran
SET LOCK_TIMEOUT 3000
UPDATE a SET dd=dd+1
--WaitFor Delay '00:00:10';
SELECT * FROM B
ROLLBACK tran
--3秒鍾就會終止當前SQL的執行,不會影響后面的執行效率