postgresql - 人们预订事件,如何正确限制最大预订数量? (并发)

标签 postgresql symfony concurrency

我想这是一道经典的并发题。

有人报名参加事件。该事件可以容纳最大数量的参与者。

这是一个带有 PostgreSQL 数据库的 Symfony 应用程序。

确保事件不会超额预订的最佳方法是什么?

假设我有名为 Event、Person 和 Booking 的实体。 Booking 与 Person 和 Event 具有一对多关系。

我显示一个关于事件的页面。我计算当前的预订,如果计数小于最大值,则显示“立即预订”按钮。

这是我之前如何完成此操作的一些伪代码:

关于“立即预订”按钮的操作:

Count bookings
if count >= max
  return "Sorry, this event is full"
else
  Create booking
  Flush entity manager

  Count bookings again

  if count > max
     Delete booking
     return "Sorry, this event is full"
  endif

结束

我认为这种方法是安全的,但并不理想。我认为这可能会导致两个人在剩下一个空间时预订,但都被拒绝了。发生这种情况的真实可能性可能接近于零,我想用户会再试一次,但是......正确地做到这一点会很好。

有更好的方法吗?

我读过这个:Handling the concurrent request while persisting in oracle database?以及几个月前我问过的一个类似问题。当最大预订量 = 1 时(例如飞机座位),乐观锁定似乎是一个很好的策略。在那种情况下,我可能根本不会有 Booking 实体。事件将只有一个人或没有。

最佳答案

看看学说文档 Concurrency and Transactions , 您可以使用几个选项。

我同意乐观锁定可能是可行的方法,但您不必更改当前的逻辑。只需向要插入的实体添加一个新的 version 字段(类型 serial 最好),当您执行初始 SELECT 时,您传入唯一的版本号.然后插入的时候,如果版本变了,就知道别人已经预定了,插入就不会发生了。

文档中有一些很好的例子 Optimistic Locking

更新

乐观锁定将在更新实体时起作用。对于插入新实体,交易将是最好的选择。

关于postgresql - 人们预订事件,如何正确限制最大预订数量? (并发),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22150920/

相关文章:

php - 在 jquery 中,调用用户定义的函数在 google chrome 中有效,但在 mozilla 中无效

ios - CoreData 并发问题

ruby-on-rails - rails 和 Postgres : Migration to change_colomn gives error "cannot be cast to type timestamp without time zone"

postgresql - 更改 PostgreSQL 数据库及其表的所有者的最佳方法?

postgresql - 如何在 Postgres 事件触发器中获取更改表的名称?

php - 如何告诉 symfony 加载我的自定义 routing.yml 配置

postgresql - 在 Postgres 中的特定模式上创建序列时出错

php - 安装/激活运行 MAMP 的 PHP "intl"扩展

goroutine race condition 解决方案

c# - 在更新排序和显示时在并发字典中获取参数异常