Tôi có một bảng trông giống như sau:Cách xử lý các yêu cầu đồng thời xóa và tạo các hàng giống nhau?
game_stats bảng:
cậpid | game_id | player_id | stats | (many other cols...)
----------------------
1 | 'game_abc' | 8 | 'R R A B S' | ...
2 | 'game_abc' | 9 | 'S B A S' | ...
Một người sử dụng dữ liệu cho một trò chơi được đưa ra trong số lượng lớn, gửi dữ liệu cả hai người chơi cùng một lúc. Ví dụ:
"game": {
id: 'game_abc',
player_stats: {
8: {
stats: 'R R A B S'
},
9: {
stats: 'S B A S'
}
}
}
Việc gửi điều này đến máy chủ của tôi sẽ dẫn đến bảng đầu tiên.
Thay vì cập nhật hàng hiện có khi cùng một dữ liệu được gửi một lần nữa (với các phiên bản, ví dụ) những gì tôi làm trong điều khiển của tôi là lần đầu tiên xóa tất cả các hàng hiện có trong game_stats
bảng mà có game_id đưa ra:
class GameStatController
def update
GameStat.where("game_id = ?", game_id).destroy_all
params[:game][:player_stats].each do |stats|
game_stat.save
end
end
end
Tính năng này hoạt động tốt với một máy chủ xử lý luồng đơn hoặc luồng đơn. Vấn đề là tôi đang chạy Unicorn, đó là một máy chủ đa quy trình. Nếu hai yêu cầu đến cùng một lúc, tôi sẽ nhận được một điều kiện chủng tộc:
Request 1: GameStat.where(...).destroy_all
Request 2: GameStat.where(...).destroy_all
Request 1: Save new game_stats
Request 2: Save new game_stats
Kết quả: Nhiều hàng trò chơi có cùng dữ liệu.
Tôi tin rằng bằng cách nào đó khóa các hàng hoặc bảng là cách để ngăn chặn nhiều bản cập nhật cùng một lúc - nhưng tôi không thể tìm ra cách thực hiện. Kết hợp với một giao dịch có vẻ là điều đúng đắn để làm, nhưng tôi không thực sự hiểu tại sao.
EDIT
Để làm rõ lý do tại sao tôi không thể tìm ra cách để sử dụng khóa: Tôi không thể khóa một hàng duy nhất tại một thời điểm, vì hàng chỉ đơn giản là xóa và không sửa đổi.