2012-10-06 25 views
9

Tôi muốn các giao dịch đồng thời chọn một hàng từ bảng, đánh dấu là "bẩn" để các giao dịch khác không thể chọn nó, sau đó thực hiện phần còn lại của Giao dịch.Ví dụ tối thiểu sử dụng lựa chọn ... để cập nhật cách ly hàng

Tôi gặp sự cố khi sử dụng select... for update cho mục đích này vì giao dịch thứ hai có ý nghĩa như nhau. Vui lòng cung cấp ví dụ tối thiểu cho các giao dịch khác nhau để chọn các hàng riêng biệt.

dữ liệu của tôi là:

mysql> select * from SolrCoresPreallocated; 
+----+-------------+-----+-----+ 
| id | used_status | sid | cid | 
+----+-------------+-----+-----+ 
| 1 |   0 | 0 | 400 | 
| 2 |   0 | 0 | 401 | 
| 3 |   0 | 0 | 402 | 
| 4 |   0 | 0 | 403 | 
| 5 |   0 | 0 | 404 | 
| 6 |   0 | 0 | 405 | 
+----+-------------+-----+-----+ 
6 rows in set (0.00 sec) 

Và công cụ này không hoạt động như mong đợi:

mysql> begin; 
Query OK, 0 rows affected (0.00 sec) 

mysql> select * from SolrCoresPreallocated order by id limit 1 for update; 
+----+-------------+-----+-----+ 
| id | used_status | sid | cid | 
+----+-------------+-----+-----+ 
| 1 |   0 | 0 | 400 | 
+----+-------------+-----+-----+ 
1 row in set (0.00 sec) 

...set the used_status to 1 
...perform the rest of the operations 

... như giao dịch thứ hai trở đi

mysql> begin; 
Query OK, 0 rows affected (0.00 sec) 

mysql> select * from SolrCoresPreallocated order by id limit 1 for update; 
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 
mysql> rollback; 
Query OK, 0 rows affected (0.00 sec) 
+0

Chính xác những gì bạn làm không mong đợi? –

+0

bao gồm rằng quá – aitchnyu

Trả lời

7

SELECT ... FOR UPDATE khóa hàng (s) trong chế độ độc quyền, có nghĩa là lựa chọn thứ hai không thể tiếp tục cho đến khi lựa chọn đầu tiên có ted hoặc cuộn lại. Điều này là do kết quả của lựa chọn thứ hai có thể bị ảnh hưởng bởi nội dung của hàng bạn đã khóa, vì vậy cần phải có khóa đọc để hàng kiểm tra.

Nếu bạn tạo UNIQUE INDEX trên ví dụ id, bạn có thể làm;

select * from SolrCoresPreallocated where id=1 for update; 

trong giao dịch đầu tiên và;

select * from SolrCoresPreallocated where id=2 for update; 

trong phần thứ hai độc lập, vì chỉ mục duy nhất cho phép lựa chọn thứ hai tìm hàng chính xác mà không cần đọc khóa đầu tiên.

EDIT: Để nhận hàng "miễn phí" nhanh nhất có thể, cách duy nhất thực sự là thực hiện hai giao dịch;

  • BEGIN/SELECT FOR UPDATE/UPDATE to busy/COMMIT để nhận hàng.
  • BEGIN/< hàng xử lý>/UPDATE để miễn phí/COMMIT xử lý hàng và giải phóng hàng.

Điều này có nghĩa là bạn có thể cần các hành động bù trừ trong trường hợp quy trình không thành công và quay lại giao dịch sẽ CẬP NHẬT hàng miễn phí, nhưng vì MySQL (hoặc SQL chuẩn cho vấn đề đó) không có khái niệm "có được hàng mở khóa tiếp theo", bạn không có nhiều tùy chọn.

+0

Nhưng tôi cần phải chọn ** hàng miễn phí ** tiếp theo; Tôi không thể truy vấn như thế này, mặc dù nó hoạt động – aitchnyu

+0

@aitchnyu Đã thêm một chỉnh sửa cho câu trả lời. –

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