2012-12-26 44 views
10

Tôi có một v_ext bảng trong một MySQL với InnoDB:
- id: chính chủ chốt
- Mã: pre-tạo danh sách các mã (nói 1000 mã được tạo ngẫu nhiên)
- user_id: ban đầu NULLMySQL InnoDB SELECT ... LIMIT 1 FOR UPDATE Vs CẬP NHẬT ... LIMIT 1

Khi người dùng mua một mặt hàng, họ sẽ nhận được mã. Tôi cần cập nhật bảng để điền cột user_id. Tôi có hai lựa chọn:

START TRANSACTION; 
SELECT id FROM v_ext WHERE user_id IS NULL LIMIT 1 FOR UPDATE; -- return id 54 for ex. 
UPDATE v_ext SET user_id=xxx WHERE id=54; 
COMMIT; 

hoặc

UPDATE v_ext SET user_id=xxx WHERE user_id IS NULL LIMIT 1; 

là tùy chọn thứ hai an toàn nếu tôi có hàng ngàn người dùng mua cùng một lúc? Nếu vậy, có đúng không khi giả sử tùy chọn thứ hai này tốt hơn cho hiệu suất vì nó chỉ cần một truy vấn?

+0

Có ràng buộc 'UNIQUE' trên' user_id' không? (nghĩa là người dùng chỉ có thể có một mã)? – eggyal

+0

'EXISTS' sẽ là sử dụng tốt hơn về mặt đồng thời và hiệu suất. – bonCodigo

+0

UNIQUE không phải là một ràng buộc, user_id có thể nhận được nhiều mã khi họ mua hàng – JScoobyCed

Trả lời

10

Vì tôi không nhận được câu trả lời, tôi bắt đầu làm điểm chuẩn. tiêu chí của tôi như sau:

  • 20.000 mã trước tạo
  • Sử dụng Apache ab lệnh với 20.000 yêu cầu, 100 đồng thời: ab -n 20000 -c 100
  • Servlet -> EJB (JPA 2,0 EclipseLink, JTA) để thực hiện các cập nhật trong DB (vì nó sẽ thông qua một hành động JSF trong tình huống thực tế)
  • 2 phiên bản của Servlet, một phiên bản với tùy chọn 1 (SELECT ... FOR UPDATE), và một với tùy chọn 2 (UPDATE ... LIMIT 1)
  • Ngắt Glassfish, nhấn Servlet đã kiểm tra theo cách thủ công 5 lần để làm ấm nó lên, đặt lại tất cả để NULL để user_id
  • Các xét nghiệm được chạy 3 lần mỗi và trung bình được cung cấp

Kết quả:

SELECT ... FOR UPDATE; CẬP NHẬT ...:

Concurrency Level:  100 
Time taken for tests: 758.116 seconds 
Complete requests:  20000 
Failed requests:  0 
Write errors:   0 
Row updated:   20000 

CẬP NHẬT .... LIMIT 1:

Concurrency Level:  100 
Time taken for tests: 773.659 seconds 
Complete requests:  20000 
Failed requests:  0 
Write errors:   0 
Row updated:   20000 

Vì vậy, ít nhất là trên hệ thống của tôi, tùy chọn với 2 câu hỏi dường như hiệu quả hơn so với một truy vấn. Tôi không mong đợi điều đó :)

+0

+1 Phát hiện thú vị. Nó có gây ra bất kỳ vấn đề tương tranh nào không? –

+0

Không phải là tôi có thể nhìn thấy. Tôi đã cập nhật 20.000 hàng thông qua 20.000 yêu cầu thành công. – JScoobyCed

+0

Câu hỏi tiếp theo với bế tắc chỉ xảy ra khi tôi chỉ mục user_id thực sự là cột varchar) http://stackoverflow.com/questions/14052038/mysql-select-for-update-with-index-has-concurrency-issue – JScoobyCed

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