gpt4 book ai didi

sql - Rails:使用 Postgres 创建对象时重复 ActiveRecord::RecordNotUnique?

转载 作者:数据小太阳 更新时间:2023-10-29 07:08:52 26 4
gpt4 key购买 nike

我正在使用 Rails 4 应用程序,它需要创建大量对象以响应来自另一个系统的事件。当我调用 create! 时,主键列上出现非常频繁的 ActiveRecord::RecordNotUnique 错误(由 PG::UniqueViolation 引起)我的模型之一。

我在 SO 上找到了其他答案,建议挽救异常并调用 retry:

begin
TableName.create!(data: 'here')
rescue ActiveRecord::RecordNotUnique => e
if e.message.include? '_pkey' # Only retry primary key violations
log.warn "Retrying creation: #{e}"
retry
else
raise
end
end

虽然这似乎有所帮助,但对于数据库中已存在的顺序 ID(日志条目已缩写),我仍然遇到 ActiveRecord::RecordNotUnique 错误:

WARN -- Retrying creation: PG::UniqueViolation: DETAIL: Key (id)=(3067) already exists.
WARN -- Retrying creation: PG::UniqueViolation: DETAIL: Key (id)=(3068) already exists.
WARN -- Retrying creation: PG::UniqueViolation: DETAIL: Key (id)=(3069) already exists.
WARN -- Retrying creation: PG::UniqueViolation: DETAIL: Key (id)=(3070) already exists.

它正在尝试的 ID 在 3000-4000 范围内,即使有问题的表中有超过 90000 条记录。

为什么 ActiveRecord 或 PostgreSQL 会浪费这么多时间依次尝试现有 ID?


原始异常(简化/删除查询字符串):

{
"exception": "ActiveRecord::RecordNotUnique",
"message": "PG::UniqueViolation: ERROR: duplicate key value violates unique constraint \"table_name_pkey\"\nDETAIL: Key (id)=(3023) already exists."
}

最佳答案

我不确定这是怎么发生的,但事实证明表主键的 PostgreSQL 序列以某种方式被重置或与表不同步:

SELECT nextval('table_name_id_seq');
-- 3456

SELECT max(id) FROM table_name;
-- 95123

我必须在表的最后一个 ID 处重新启动主键序列:

ALTER SEQUENCE table_name_id_seq RESTART 95124;

更新:这是一个 Rake 任务,用于为带有 PostgreSQL 的 Rails 4 项目中的大多数模型重置 ID 序列:

desc 'Resets Postgres auto-increment ID column sequences to fix duplicate ID errors'
task :reset_sequences => :environment do
Rails.application.eager_load!

ActiveRecord::Base.descendants.each do |model|
unless model.attribute_names.include?('id')
Rails.logger.debug "Not resetting #{model}, which lacks an ID column"
next
end

begin
max_id = model.maximum(:id).to_i + 1
result = ActiveRecord::Base.connection.execute(
"ALTER SEQUENCE #{model.table_name}_id_seq RESTART #{max_id};"
)
Rails.logger.info "Reset #{model} sequence to #{max_id}"
rescue => e
Rails.logger.error "Error resetting #{model} sequence: #{e.class.name}/#{e.message}"
end
end
end

以下引用被证明是有用的:

关于sql - Rails:使用 Postgres 创建对象时重复 ActiveRecord::RecordNotUnique?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28639439/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com