sql - Rails ActiveRecord - 如何锁定表以供读取?

标签 sql ruby-on-rails postgresql activerecord locking

我有一些 Rails ActiveRecord 代码,如下所示:

new_account_number = Model.maximum(:account_number)
# Some processing that usually involves incrementing
# the new account number by one.
Model.create(foo: 12, bar: 34, account_number: new_account_number)

此代码本身运行良好,但我有一些由 DelayedJob 工作程序处理的后台作业。有两个工作人员,如果他们都开始处理一批处理此代码的作业,他们最终会创建具有相同 account_number 的新 Model 记录,因为找到最大值和创建之间存在延迟一个更高帐号的新记录。

目前,我已经通过在数据库级别向模型表添加唯一性约束来解决此问题,然后通过重新选择最大值来重试,以防此约束触发异常。

然而,这感觉像是一个 hack。

在数据库级别向 account_number 列添加自动递增不是一个选项,因为 account_number 分配需要的不仅仅是递增。

理想情况下,我想锁定有问题的表以供读取,这样在我完成之前,其他人无法对该表执行最大选择查询。但是,我不确定该怎么做。我正在使用 Postgresql。

最佳答案

基于 the ActiveRecord::Locking docs看起来 Rails 没有为表级锁提供内置 API。

但是您仍然可以使用原始 SQL 执行此操作。对于 Postgres,这看起来像

ActiveRecord::Base.transaction do
  ActiveRecord::Base.connection.execute('LOCK table_name IN ACCESS EXCLUSIVE MODE')
  ...
end

锁必须在事务中获取,并在事务结束后自动释放。

请注意,您在此处使用的 SQL 将根据您的数据库而有所不同。


显然锁定整个表并不优雅或高效,但对于小型应用程序,在一段时间内,它可能确实是最好的解决方案。这很简单,也很容易推理。一般来说,建议锁更适合这种数据竞争。

关于sql - Rails ActiveRecord - 如何锁定表以供读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24587403/

相关文章:

sql - 按组从表中获取Max()记录

php - 如何使用多次出现的项目构建具有偏差的mysql查询

mysql - 如何在必须检查多个属性的关系数据库中选择属性?

javascript - Javascript 中带父级和不带父级的 json 上的 .map 方法

sql-server - StreamSets Data Collector 能否在目标数据库中自动创建表?

postgresql - 从插入中选择

sql - SQLITE:通过RowID删除记录

ruby-on-rails - 正则表达式:查找斜杠和网址中匹配关键字之间的单词

ruby-on-rails - 如何在 Rails 2.3 中测试多态 Controller ?

postgresql - PRAGMA foreign_keys = ON 相当于 Postgresql