Ví dụ của bạn trong câu hỏi của bạn cho thấy thứ tự khóa phụ thuộc vào phương thức truy cập. Đường dẫn truy cập này không được quyết định trực tiếp bởi mệnh đề ORDER BY của truy vấn, có nhiều yếu tố có thể ảnh hưởng đến đường dẫn truy cập này. Do đó, bạn không thể ngăn chặn bế tắc chỉ bằng cách thêm một ĐƠN ĐẶT HÀNG BẰNG vì bạn vẫn có thể có hai đường dẫn truy cập riêng biệt. Trên thực tế, bằng cách chạy trường hợp thử nghiệm của bạn với thứ tự và thay đổi các tham số phiên, tôi đã có thể khiến hai phiên chạy vào một ORA-60 với cùng một truy vấn.
Nếu các phiên liên quan không có khóa nào khác đang chờ xử lý, hãy khóa các hàng theo cùng một thứ tự trong tất cả các phiên sẽ ngăn chặn bế tắc nhưng làm thế nào bạn có thể buộc lệnh này một cách đáng tin cậy? Lưu ý rằng dù sao thì điều này cũng chỉ ngăn chặn trường hợp deadlock rất đặc biệt này. Bạn vẫn có thể gặp bế tắc với nhiều truy vấn trong mỗi phiên hoặc các kế hoạch khác nhau.
Trên thực tế, trường hợp này thực sự đặc biệt và dù sao cũng không nên xảy ra thường xuyên:nếu bạn lo lắng về các bế tắc, tôi vẫn nghĩ có nhiều phương pháp dễ dàng hơn để ngăn chặn chúng.
Cách dễ nhất để ngăn chặn bế tắc là sử dụng FOR UPDATE NOWAIT
hoặc FOR UPDATE WAIT X
(mặc dù WAIT X vẫn có thể kích hoạt bế tắc với các giá trị của X vượt trội hơn so với cơ chế phát hiện bế tắc, tôi tin rằng hiện tại là 3 giây kể từ 11g - cảm ơn @ APC
để sửa chữa).
Nói cách khác, cả hai giao dịch nên yêu cầu:cung cấp cho tôi những hàng đó và khóa chúng nhưng nếu người dùng khác đã có khóa sẽ trả lại lỗi thay vì chờ vô thời hạn. Chính sự chờ đợi vô thời hạn đã gây ra bế tắc.
Trong thực tế, tôi sẽ nói rằng hầu hết các ứng dụng với người dùng thực thà nhận lỗi ngay lập tức hơn là để một giao dịch chờ vô thời hạn cho một giao dịch khác kết thúc. Tôi sẽ cân nhắc FOR UPDATE
không có NOWAIT
chỉ dành cho các công việc hàng loạt không quan trọng.