Array.pop竞争条件

时间:2015-02-03 19:11:29

标签: ruby-on-rails arrays concurrency race-condition pop

系统上的3个用户同时点击买票

模型

class TicketInventory < ActiveRecord::Base
  serialize :ticket_roll, Array
end 

ticket_roll播种了一系列数字

控制器

ticket_inventory = TicketInventory.find(1)
ticket_roll = ticket_inventory.ticket_roll
TicketInventory.transaction do
  @ticket = ticket_roll.pop
  ticket_inventory.save
end

他们都得到同样的票。

我已经考虑过lock_version,但这会引发错误,而不是提供下一张票。

我也查看了索引,但每张票需要一行。

如何避免这种竞争条件?

1 个答案:

答案 0 :(得分:2)

您是否尝试使用ActiveRecord::Locking::Pessimistic。它使用事务和数据库锁。它根据文档支持PostgreSQL和MySQL:

MySQL: http://dev.mysql.com/doc/refman/5.1/en/innodb-locking-reads.html
PostgreSQL: http://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE

您可以这样使用它:

ticket_inventory = TicketInventory.find(1)
ticket_inventory.with_lock do
  ticket_roll = ticket_inventory.ticket_roll
  @ticket = ticket_roll.pop
  ticket_inventory.save
end

尝试一下,它可能会起作用。