Mặc dù đây không phải là giải pháp tốt nhất, vì không có cách nào tôi biết để bỏ qua các hàng bị khóa, tôi chọn một hàng ngẫu nhiên và cố gắng lấy khóa.
START TRANSACTION;
SET @v1 =(SELECT myId FROM tests.table WHERE status is NULL LIMIT 1);
SELECT * FROM tests.table WHERE [email protected] FOR UPDATE; #<- lock
Đặt thời gian chờ nhỏ cho giao dịch, nếu hàng đó bị khóa giao dịch bị hủy và tôi thử một giao dịch khác. Nếu tôi lấy khóa, tôi xử lý nó. Nếu (may mắn) hàng đó bị khóa, nó được xử lý và khóa được giải phóng trước khi hết thời gian chờ của tôi, sau đó tôi chọn một hàng đã được 'xử lý'! Tuy nhiên, tôi kiểm tra một trường mà quy trình của tôi được đặt (ví dụ: trạng thái): nếu giao dịch quy trình khác kết thúc OK, trường đó cho tôi biết rằng công việc đã được thực hiện và tôi không xử lý lại hàng đó. Tất cả các giải pháp có thể khác không có giao dịch (ví dụ như thiết lập một trường khác nếu hàng không có trạng thái và ... vv) có thể dễ dàng cung cấp điều kiện chủng tộc và quy trình bị mất (ví dụ: một chuỗi đột ngột chết, dữ liệu được phân bổ vẫn được gắn thẻ, trong khi một giao dịch hết hạn;. ref bình luận here
Hy vọng nó giúp
Nguồn
2017-07-06 09:34:42
1 sử dụng LIMIT là một ý tưởng tốt –
Trong ví dụ này, nếu kịch bản đột ngột bị hủy bỏ sau khi cập nhật đầu tiên, sẽ như thế nào bạn "làm sạch". Nếu không thì 100 hàng đó sẽ không bao giờ được xử lý. –
Câu hỏi hay. Tôi thường đặt cùng một cột hoặc một ' cột của tiểu bang để cho biết hoàn thành thành công (như là một phần của giao dịch). Sau đó, nếu một quá trình chết, bạn có thể đặt bất kỳ process_id cho một quá trình không tồn tại trở lại NULL cho một quá trình để chọn lên. Tôi thích công việc cron cho việc dọn dẹp, nhưng bạn cũng có thể làm cho nó trở thành một phần của việc bắt đầu một quy trình mới. –