【问题标题】:Atomicity of multiple database transactions on HerokuHeroku 上多个数据库事务的原子性
【发布时间】:2011-04-03 04:20:10
【问题描述】:

我的问题很简单,但我对 Rails (以及 Web 编程)有点陌生,找不到好的答案。如何确保两个(或更多)数据库事务在 Heroku 上原子发生?

我能否像使用任何多线程应用程序一样使用互斥锁对应用程序进行编码,并期望它在 Heroku 等分布式服务器环境中正常工作?如果不是,那么确保两个或多个数据库事务的原子性的最佳方法是什么?

我知道 Heroku 使用 PostgreSQL,它可以让我获得一组数据库锁,但这些锁只持续一个事务。此外,我熟悉用于同步多线程应用程序的互斥锁(和 pthreads),但我不确定这些约定是否会在 Heroku 上按预期工作,尤其是当我的实际应用程序代码在多个服务器上运行时。

编辑

我绝对应该多解释一下我想要做的事情。我需要对数据库进行两次调用。第一次调用是读取一个布尔值。如果那个布尔值为真,我需要做一些动作,如果它是假的,我需要做一些别的事情。如果我读到 TRUE,那么我需要做一些其他的事情(与外部 API 的接口等......),如果成功,那么我需要将布尔值设置为 false。问题是我不知道如何避免多个客户端从数据库读取 true 的情况,而实际上,一个客户端正在写入 false 但尚未完成我之前需要做的其他事情写假。

【问题讨论】:

  • 这将有助于了解您为什么需要 2 个单独的交易。是什么阻止您将更多操作放入单个事务中?

标签: ruby-on-rails database heroku atomic


【解决方案1】:

这是一个可能可行的替代方案:

修改布尔字段以允许存储三态变量。 (日期/时间也可以,我会稍微解释一下。)

然后像这样编码操作:

begin transaction
    read flag
    if true
         set flag to "processing" state
    if false
         perform other activity
commit

如果标志是true,那么现在将设置为processing;调用外部 API,做任何事情,当结果已知时:

begin transaction
    read flag
    if "processing"
        set flag to false
    if true
        warn loudly
    if false
        warn loudly
commit

当然,如果处理外部 API 的进程死亡或阻塞太久,您会想知道并能够恢复。这就是为什么将日期/时间存储到标志中会很好的原因——如果它已经处于processing 状态六分钟,那么杀死它并重新启动。

使用 posix 信号量或类似工具会有一些好处,但我希望您的 Rails 后端进程可能每分钟在不同的机器上执行。

【讨论】:

  • 有趣。我一定要试试这个。如果两个进程设法到达 API 阶段并连续读取第二个代码块中的“处理”标志状态,似乎仍然可能存在“竞争条件”。但是,发生这种情况的可能性非常低(我认为)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-09
相关资源
最近更新 更多