🔍解密「系統鎖死」:用日常語言看懂軟體工程師如何解決資料庫死結問題
🔍 前言:看似神秘的「鎖死」到底是什麼?
想像一下,你和朋友一起在冰箱裡拿飲料。你拉著冰箱門不放,朋友又同時拉著同一扇門。結果?誰也打不開,大家都卡住。
這種情況在資料庫裡也會發生,專業名稱叫做 「死結(Deadlock)」。
這次的案例發生在一個自動處理晶圓資料(wafer data)的系統裡。系統同時開了多個背景任務,一邊在刪資料、一邊在更新資料。結果不同的任務互相「鎖住」了資料庫資源,造成 SQL Server 無法繼續執行。
🧠 為什麼會發生死結?
死結不是 bug,而是資料庫「太忙」的副作用。
簡單來說,當:
-
任務 A 鎖住了表 A,準備要動表 B
-
任務 B 鎖住了表 B,準備要動表 A
兩個任務互相等待,資料庫就陷入「我等你、你等我」的無限循環。
SQL Server 為了救場,會強制中止其中一個任務,留下錯誤訊息:
「交易在鎖定資源上被另一個處理序鎖死,已被選為犧牲者。」
⚙️ 軟體工程師怎麼解決?
這類問題聽起來複雜,其實解法可以用生活邏輯來理解。
1️⃣ 讓資料庫「找得到路」
在刪除資料時,如果資料庫沒有地圖(索引),它會整張表掃描,鎖住很多筆資料。
工程師會幫它加上「快速搜尋索引」,像是:
-
幫每筆資料加上標籤(例如「物件編號」)
-
讓刪除只影響該筆資料,不會把整張表鎖起來
👉 結果:刪除變快,鎖衝突變少。
2️⃣ 固定「刪除順序」
想像你和朋友要清冰箱:一個先清上層、另一個先清下層。
如果大家都用不同順序,就容易互卡。
同樣的,系統也要統一先刪表 A 再刪表 B,避免交叉鎖。
3️⃣ 加上「重試機制」
死結常常是「暫時的衝突」。
工程師會加上簡單的自動重試邏輯:
若第一次失敗,等個一秒再試一次,通常第二次就成功。
這樣就像遊樂園入口排隊,第一輪人太多就稍等再進。
4️⃣ 減少同時開太多執行緒
如果同時開十個任務都在刪資料,衝突機率自然變高。
將同時處理數降到兩三個,可以顯著減少問題。
(有點像餐廳廚師太多也會互相撞鍋)
5️⃣ 啟用「快照讀取模式」
資料庫有個設定叫 Read Committed Snapshot。
開啟後,資料庫會「拍一張快照」給讀取端,讓讀取和刪除互不干擾。
這招非常適合同時有多任務運作的系統。
🚀 結果:系統重新穩定,效能更好
經過上述優化後,系統重新跑起來:
-
每批資料處理時間從 3 分鐘降到 1 分半
-
不再出現「鎖死犧牲者」的錯誤
-
所有檔案能穩定進入資料庫
使用者不再看到失敗通知,整個流程自動、穩定又快速。
🏁 結語
死結看似可怕,其實是系統在「自我保護」。
只要了解它發生的原因,並透過索引、順序、重試與限制併發,就能輕鬆避免。
用一句話總結:
「死結不是錯,而是系統在提醒你該排隊了。」
留言
張貼留言