首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ActiveRecord触摸对多个工作人员是否同时安全?

ActiveRecord触摸对多个工作人员是否同时安全?
EN

Stack Overflow用户
提问于 2018-04-03 21:52:22
回答 1查看 132关注 0票数 3

假设我有两个工作人员(W1,W2)并行运行同一个作业(sidekiq不能保证一个作业只运行一次,所以可能会发生这种情况)。

作业:

代码语言:javascript
复制
car.touch(:read_at)
cars = Car.where.not(read_at: nil).order(read_at: :asc).limit(1)
send_user_email if cars.include?(car)

问题的非并发版本:

  • 19:00:01: W1触摸read_at
  • 19:00:02: W1查询汽车,使用not read_at.nil?获取最老的car
  • 19:00:03: W1向用户发送电子邮件.
  • 19:00:04: W2触摸read_at
  • 19:00:05: W2查询汽车,使用not read_at.nil?获取最老的car
  • 19:00:06: W2返回,不发送电子邮件.
  • 用户收到一封电子邮件。

问题的并发版本:

  • 19:00:01: W1触摸read_at。AR用read_at=19:00:01向数据库发送一个写。W1与DB的连接出现问题,并且尚未执行写操作。
  • 19:00:02: W2触摸read_at。AR用read_at=19:00:02向数据库发送一个写。W2有很好的连接,执行DB写。
  • 19:00:03: W2查询汽车,使用not read_at.nil?获取最老的car
  • 19:00:04: W2向用户发送电子邮件,W1写入仍未执行.
  • 19:00:05:对DB执行W1写。
  • 19:00:06: W1查询汽车,用not read_at.nil?获取最老的car。现在,来自W1的car是最古老的,写是在W2之后执行的,但是由于命令是read_at=19:00:01,对于read_at=19:00:02,W1中的car将比W2中的car更老。
  • 19:00:07: W1向用户发送电子邮件.
  • 用户收到2封电子邮件。

这种情况(并发版本)有可能发生吗?如果是,那么AR为什么不使用DBs函数来用touch更改时间戳(例如,postgresql NOW())。

使用NOW()将使W1 read_at总是比W2 read_at更新。

EN

回答 1

Stack Overflow用户

发布于 2018-04-10 17:42:12

Rails不使用数据库本机函数的一个很好的原因(如果不是主要的原因)是,您的数据库不知道Rails应用程序使用的是哪个时区。

一旦您可以将配置时区转到您的数据库服务器之外的其他地方,每当您调用car.touch(:read_at)时,Rails都需要告诉您的数据库到底将保持什么。

另一件需要考虑的事情是,您的员工应该是幂等。换句话说,您应该让您的代码意识到这些可能的种族条件,并保护自己不受它们的影响。正如您可能已经想到的那样,一种解决方案是为数据库事务添加适当的锁。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49639683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档