🔒 Deadlock trong SQL Server là gì?
Deadlock (bế tắc) xảy ra khi hai hoặc nhiều giao dịch (transactions) giữ khóa tài nguyên và chờ nhau giải phóng một tài nguyên khác, dẫn đến vòng lặp chờ vô tận – không giao dịch nào tiếp tục được.
🧠 Ví dụ minh họa đơn giản
| Giao dịch A | Giao dịch B |
| --------------------------- | ------------------------------ |
| 1. Lock bảng Customers | |
| | 1. Lock bảng Orders |
| 2. Chờ lock bảng Orders | 2. Chờ lock bảng Customers |
➡️ Cả 2 giao dịch đều chờ nhau mãi mãi → Deadlock!
❗ SQL Server xử lý deadlock như thế nào?
SQL Server tự động chọn 1 giao dịch để hủy (gọi là "victim"), và thông báo lỗi:
Transaction (Process ID xx) was deadlocked on resources...
📌 Nguyên nhân gây deadlock
- ❌ Cập nhật nhiều bảng theo thứ tự khác nhau giữa các transaction
- ❌ Giao dịch mở quá lâu, giữ khóa lâu
- ❌ Thiếu chỉ số (index) dẫn đến table scan và khóa toàn bộ bảng
- ❌ Không dùng giao dịch đúng cách (thiếu COMMIT/ROLLBACK)
- ❌ Khóa mức cao (như khóa bảng thay vì khóa dòng)
✅ Cách phòng tránh và xử lý Deadlock
🔄 1. Giữ thứ tự truy cập tài nguyên nhất quán
- Các transaction nên truy cập bảng theo cùng một thứ tự
-- Tất cả transaction truy cập theo thứ tự: A ➝ B ➝ C
⏳ 2. Giữ giao dịch càng ngắn càng tốt
- Tránh thực hiện thao tác người dùng (như
WAIT, PRINT,...) giữa BEGIN và COMMIT
⚡ 3. Dùng chỉ số (index) để giảm quét bảng
- Chỉ số giúp truy cập nhanh hơn, ít khóa hơn
🔐 4. Dùng NOLOCK hoặc READ COMMITTED SNAPSHOT (khi phù hợp)
- NOLOCK có thể gây dirty read nhưng giúp tránh khóa
🔁 5. Bắt lỗi và thử lại (retry) khi bị deadlock
DECLARE @Retry INT = 3;
WHILE @Retry > 0
BEGIN
BEGIN TRY
BEGIN TRANSACTION;
-- Câu lệnh có thể gây deadlock
UPDATE Products SET Quantity = Quantity - 1 WHERE ProductID = 1;
COMMIT;
BREAK; -- Thành công thì thoát vòng
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 1205 -- Mã lỗi deadlock
BEGIN
SET @Retry -= 1;
WAITFOR DELAY '00:00:01'; -- đợi 1 giây rồi thử lại
END
ELSE
BEGIN
ROLLBACK;
THROW;
END
END CATCH
END
🔍 Kiểm tra Deadlock trong SQL Server
Cách theo dõi:
- SQL Server Profiler: Theo dõi sự kiện “Deadlock Graph”
- System Health Extended Events: Mặc định ghi lại deadlock
- sys.dm_tran_locks: Xem các khóa đang giữ
SELECT * FROM sys.dm_tran_locks;
🏁 Tóm tắt
| Nội dung | Tóm tắt ngắn |
| --------------------- | ----------------------------------------------- |
| Deadlock là gì | Vòng lặp giao dịch chờ nhau dẫn đến bế tắc |
| Nguyên nhân chính | Khóa tài nguyên theo thứ tự khác, giao dịch dài |
| Xử lý | SQL Server hủy 1 giao dịch gọi là "victim" |
| Phòng tránh | Giao dịch ngắn, khóa theo thứ tự, dùng index |
| Khắc phục | Bắt lỗi 1205, retry giao dịch |