2015-04-23 20 views
5

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ập
id | 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.

Trả lời

0

AR không hỗ trợ khóa cấp bảng theo mặc định. Bạn sẽ phải thực hiện db SQL cụ thể hoặc sử dụng một gem như Monogamy

Việc kết thúc lưu các câu lệnh trong một giao dịch sẽ tăng tốc mọi thứ nếu không có gì khác.

Một giải pháp thay thế khác là triển khai khóa bằng Redis. Các đá quý như redis-lock cũng có sẵn. Điều này có thể sẽ ít rủi ro hơn vì nó không chạm vào DB, và bạn có thể thiết lập các phím Redis hết hạn.

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