2012-06-30 29 views
7

Tôi có một trang web nơi người dùng có thể mua vé, nhưng số lượng vé thường bị giới hạn và đi nhanh. Tôi đang cố gắng triển khai hệ thống ký quỹ để người dùng có thể nhấp vào họ muốn x số vé, tại thời điểm đó tôi sẽ đặt chúng ở trạng thái ký quỹ. Điều đó mang lại cho họ vài phút để nhập thông tin thẻ tín dụng của họ và hoàn tất giao dịch mua.Hoạt động nguyên tử MySQL và khóa bảng

Tôi có ba bảng có liên quan: sự kiện, vé và ký quỹ. Một hàng trong bảng sự kiện mô tả chính sự kiện, bao gồm số lượng vé tối đa có sẵn.

Bảng vé giữ sau:

user_id: người sử dụng mà mua vé

number_of_tickets: có bao nhiêu vé họ mua

event_id: sự kiện liên quan

Bảng ký quỹ giữ các thông tin sau:

user_id: người sử dụng trong quá trình mua vé

number_of_tickets: có bao nhiêu vé họ muốn

event_id: sự kiện liên quan

Hiện nay, tôi làm ba MySQL truy vấn, một cho vé tối đa, một cho số vé được bán, và một cho số vé đã được ký quỹ. Sau đó, tôi tính toán:

$remaining_tickets = $max_tickets - $tickets_sold - $tickets_in_escrow; 
if ($remaining_tickets >= $tickets_desired) 
{ 
    beginEscrow($user_id, $event_id, $tickets_desired); 
} 
else 
{ 
    echo "Error: not enough ticket remain."; 
} 

Vấn đề của tôi là có thể có nhiều người dùng thực thi mã này cùng một lúc. Nếu một người dùng được gọi beginEscrowsau một người dùng khác đã đọc số lượng vé đã được ký quỹ, có thể tôi sẽ vượt qua chương trình.

Tôi đang sử dụng công cụ InnoDB cho bảng của mình và tôi đã đọc cách khóa một hàng bằng cách sử dụng SELECT .... FOR UPDATE, nhưng tôi không cập nhật một hàng. Hàm beginEscrow sẽ chỉ chèn một hàng mới vào bảng ký quỹ. Tôi tính toán $tickets_in_escrow bằng cách đọc tất cả các hàng có id sự kiện chính xác và tăng số lượng vé cho mỗi người trong số họ.

Có lẽ tôi sắp sửa hoàn toàn sai?

Tôi có cần khóa toàn bộ bảng không?

Tôi không thể là người đầu tiên viết hệ thống ký quỹ. Tôi đã googled bản thân mình đến chết cố gắng tìm một số hướng dẫn về loại điều này, nhưng xảy ra. Bất kỳ ý tưởng nào cũng hữu ích.

Cảm ơn!

Trả lời

9

Bạn đang rất gần với thiết kế của mình nhưng không hoàn toàn ở đó.

Trước hết, bảng sự kiện của bạn cần giữ số lượng vé vẫn có sẵn cho sự kiện của bạn (ngoài bất kỳ điều gì khác bạn muốn ở đó).

Thứ hai, bảng ký quỹ của bạn cần có cột DATETIME cho biết thời điểm ký quỹ hết hạn. Bạn cần phải đặt giá trị đó bất cứ khi nào vé đi vào ký quỹ.

Thứ ba, các giao dịch đặt vé trong ký quỹ cần

  1. khóa hàng sự kiện.
  2. đọc cột vé có sẵn. (hủy bỏ nếu không có đủ)
  3. chèn một hàng vào bảng ký quỹ
  4. cập nhật hàng sự kiện để giảm cột vé có sẵn.
  5. mở khóa hàng sự kiện.

Thứ tư, hành động hoàn thành bán hàng cần xóa hàng ký quỹ và chèn hàng bán vé. Điều này không khó.

Thứ năm, bạn cần một hoạt động dọn dẹp ký quỹ. Điều này cần tìm tất cả các hàng ký quỹ đã hết hạn (có ngày hết hạn trong quá khứ) và, đối với mỗi hàng:

  1. khóa hàng sự kiện tương ứng.
  2. đọc số lượng vé ký quỹ từ bảng ký quỹ
  3. xóa hàng của bảng ký quỹ.
  4. cập nhật hàng sự kiện để tăng cột vé có sẵn.
  5. mở khóa hàng sự kiện.

Bí quyết là có số lượng có sẵn vé duy trì theo cách được lồng vào nhau đúng cách, vì vậy điều kiện chủng tộc giữa người dùng không vượt quá sự kiện của bạn.

+0

Nói cách khác, tất cả số lượng vé ký quỹ phải nằm trong một hàng duy nhất trong một bảng duy nhất, chứ không phải là tổng của các hàng trong bảng ký quỹ. Tôi thấy điều đó có ý nghĩa như thế nào. Cảm ơn. – user1493634

+0

Trên thực tế, tất cả số lượng vé - có sẵn, được ký quỹ và bán, phải nằm trong một cột của một hàng duy nhất trong một bảng duy nhất. Cột đó chạm 0, không còn chỗ để bán. Nhưng bạn có ý tưởng. –

+0

Trên StackOverflow, nếu câu trả lời giúp bạn, bạn nên chấp nhận nó bằng cách nhấp vào dấu chọn màu xanh lục. –

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