Một mẹo đơn giản có thể giúp giải quyết hầu hết các trường hợp bế tắc là sắp xếp các hoạt động theo một thứ tự cụ thể.
Bạn gặp bế tắc khi hai giao dịch đang cố gắng khóa hai ổ khóa ở các lệnh ngược nhau, tức là:
- kết nối 1:khóa chìa khóa (1), khóa chìa khóa (2);
- kết nối 2:khóa chìa khóa (2), khóa chìa khóa (1);
Nếu cả hai chạy cùng lúc, kết nối 1 sẽ khóa phím (1), kết nối 2 sẽ khóa phím (2) và mỗi kết nối sẽ đợi người kia nhả phím -> deadlock.
Bây giờ, nếu bạn đã thay đổi các truy vấn của mình sao cho các kết nối sẽ khóa các phím theo cùng một thứ tự, tức là:
- kết nối 1:khóa chìa khóa (1), khóa chìa khóa (2);
- kết nối 2:khoá khoá ( 1 ), khóa chìa khóa ( 2 );
sẽ không thể gặp bế tắc.
Vì vậy, đây là những gì tôi đề xuất:
-
Đảm bảo rằng bạn không có truy vấn nào khác khóa quyền truy cập nhiều hơn một khóa tại một thời điểm ngoại trừ câu lệnh xóa. nếu bạn làm (và tôi nghi ngờ bạn làm vậy), hãy sắp xếp WHERE của chúng trong (k1, k2, .. kn) theo thứ tự tăng dần.
-
Sửa câu lệnh xóa của bạn để hoạt động theo thứ tự tăng dần:
Thay đổi
DELETE FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
Tới
DELETE FROM onlineusers
WHERE id IN (
SELECT id FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
ORDER BY id
) u;
Một điều khác cần lưu ý là tài liệu MySQL đề xuất rằng trong trường hợp gặp sự cố, máy khách nên tự động thử lại. bạn có thể thêm logic này vào mã khách hàng của mình. (Giả sử, 3 lần thử lại lỗi cụ thể này trước khi bỏ qua).