【问题标题】:Array.pop Race ConditionArray.pop 竞争条件
【发布时间】:2019-08-27 22:02:15
【问题描述】:

系统上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,但这会引发错误,而不是提供下一张票。

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

如何避免这种竞争条件?

【问题讨论】:

  • 如果你使用乐观锁定(即lock_version)你只需要挽救错误并重试

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


【解决方案1】:

您是否尝试使用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

试试吧,应该可以的。

【讨论】:

  • 正要写这篇文章
猜你喜欢
  • 2022-01-23
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多