Cho đến nay rất tốt, điều này ít nhất sẽ ngăn người dùng thực hiện thanh toán trong nhiều phiên (nhiều lần cố gắng thanh toán cùng một thẻ - tốt để đối phó với nhấp đúp.)
Làm thế nào để bạn kiểm tra? Với một SELECT
tiêu chuẩn hoặc với SELECT ... FOR UPDATE
? Dựa trên bước 5, tôi đoán bạn đang kiểm tra một cột dành riêng trên mặt hàng hoặc một thứ gì đó tương tự.
Vấn đề ở đây là SELECT ... FOR UPDATE
ở bước 2 sẽ KHÔNG áp dụng FOR UPDATE
khóa mọi thứ khác. Nó chỉ áp dụng cho SELECT
là gì ed:the cart-item
bàn. Dựa trên tên, đó sẽ là một bản ghi khác nhau cho mỗi giỏ hàng / người dùng. Điều này có nghĩa là các giao dịch khác sẽ KHÔNG bị chặn tiếp tục.
Sau đây, dựa trên thông tin bạn đã cung cấp, bạn có thể có nhiều người mua cùng một mặt hàng, nếu bạn không sử dụng SELECT ... FOR UPDATE
trên bước 3.
Giải pháp được đề xuất
- Bắt đầu giao dịch
-
SELECT ... FOR UPDATE
cart-item
bảng.
Điều này sẽ khóa một cú nhấp đúp chuột để chạy. Những gì bạn chọn ở đây phải là một số loại cột "giỏ hàng đã đặt hàng". Nếu bạn làm điều này, giao dịch thứ hai sẽ tạm dừng ở đây và đợi giao dịch đầu tiên kết thúc, sau đó đọc kết quả mà giao dịch đầu tiên đã lưu vào cơ sở dữ liệu.
Đảm bảo kết thúc quá trình thanh toán tại đây nếu cart-item
bảng cho biết nó đã được đặt hàng.
-
SELECT ... FOR UPDATE
bảng nơi bạn ghi lại nếu một mục đã được đặt trước.
Điều này sẽ khóa các xe hàng / người dùng KHÁC không thể đọc các mục đó.
Dựa trên kết quả, nếu các mục không được đặt trước, hãy tiếp tục:
-
UPDATE ...
bảng ở bước 3, đánh dấu mục là đã đặt trước. Thực hiện bất kỳINSERT
nào khác s vàUPDATE
bạn cũng cần. -
Thanh toán. Đưa ra yêu cầu hoàn tiền nếu dịch vụ thanh toán cho biết thanh toán không hoạt động.
-
Ghi lại thanh toán, nếu thành công.
-
Giao dịch cam kết
Đảm bảo rằng bạn không làm bất kỳ điều gì có thể thất bại trong khoảng từ bước 5 đến bước 7 (như gửi email), nếu không, bạn có thể kết thúc với việc họ thực hiện thanh toán mà không được ghi lại, trong trường hợp giao dịch được khôi phục.
Bước 3 là bước quan trọng liên quan đến việc đảm bảo hai (hoặc nhiều) người không cố gắng đặt cùng một mặt hàng. Nếu hai người cùng cố gắng, người thứ hai sẽ kết thúc trang web của họ "treo" trong khi nó xử lý người đầu tiên. Sau đó, khi mục đầu tiên kết thúc, cột thứ 2 sẽ đọc cột "đặt trước" và bạn có thể gửi lại thông báo cho người dùng rằng ai đó đã mua mặt hàng đó.
Thanh toán trong giao dịch hay không
Đây là chủ quan. Nói chung, bạn muốn đóng các giao dịch càng nhanh càng tốt, để tránh nhiều người bị khóa tương tác với cơ sở dữ liệu cùng một lúc.
Tuy nhiên, trong trường hợp này, bạn thực sự muốn họ đợi. Nó chỉ là vấn đề bao lâu.
Nếu bạn chọn thực hiện giao dịch trước khi thanh toán, bạn sẽ cần ghi lại tiến trình của mình trong một số bảng trung gian, chạy thanh toán và sau đó ghi lại kết quả. Lưu ý rằng nếu thanh toán không thành công, thì bạn sẽ phải hoàn tác thủ công các hồ sơ đặt trước mặt hàng mà bạn đã cập nhật.
CHỌN ... ĐỂ CẬP NHẬT trên các hàng không tồn tại
Chỉ là một lời cảnh báo, trong trường hợp thiết kế bảng của bạn liên quan đến việc chèn các hàng mà bạn cần SELECT ... FOR UPDATE
trước đó :Nếu một hàng không tồn tại, giao dịch đó sẽ KHÔNG khiến các giao dịch khác phải đợi, nếu chúng cũng SELECT ... FOR UPDATE
cùng một hàng không tồn tại.
Vì vậy, hãy đảm bảo luôn tuần tự hóa các yêu cầu của bạn bằng cách thực hiện SELECT ... FOR UPDATE
trên một hàng mà bạn biết là tồn tại đầu tiên. Sau đó, bạn có thể SELECT ... FOR UPDATE
trên hàng có thể tồn tại hoặc có thể chưa. (Đừng cố thực hiện chỉ một SELECT
trên hàng có thể tồn tại hoặc có thể không tồn tại, vì bạn sẽ đọc trạng thái của hàng tại thời điểm giao dịch bắt đầu, không phải tại thời điểm bạn chạy SELECT
. Vì vậy, SELECT ... FOR UPDATE
trên các hàng không tồn tại vẫn là điều bạn cần làm để có được thông tin cập nhật nhất, chỉ cần lưu ý rằng nó sẽ không khiến các giao dịch khác phải chờ đợi.)