2010-11-05 38 views
6

Tôi có một bảng được đọc cùng lúc bởi các luồng khác nhau.Bỏ qua hàng bị khóa trong truy vấn MySQL

Mỗi chủ đề phải chọn 100 hàng, thực hiện một số tác vụ trên mỗi hàng (không liên quan đến cơ sở dữ liệu) thì phải xóa hàng đã chọn khỏi bảng.

hàng được lựa chọn sử dụng truy vấn này:

SELECT id FROM table_name FOR UPDATE; 

Câu hỏi của tôi là: Làm thế nào tôi có thể bỏ qua (hoặc bỏ qua) hàng mà trước đây được khóa bằng một tuyên bố chọn trong MySQL?

Trả lời

15

tôi thường tạo ra một cột PROCESS_ID đó là mặc định NULL và sau đó có mỗi thread sử dụng một định danh duy nhất để làm như sau:

UPDATE table_name SET process_id = #{process.id} WHERE process_id IS NULL LIMIT 100; 

SELECT id FROM table_name WHERE process_id = #{process.id} FOR UPDATE; 

Điều đó đảm bảo rằng mỗi thread chọn một bộ duy nhất của dòng trong bảng.

Hy vọng điều này sẽ hữu ích.

+1

1 sử dụng LIMIT là một ý tưởng tốt –

+1

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ý. –

+1

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. –

0

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

Các vấn đề liên quan