postgresql – postgres数据库错误强制重启事务

TL; DR:在AR :: Base保存事务中插入重复的连接表记录失败(由于唯一约束)导致保存失败和回滚.不添加重复的连接表记录是好的.不节约是坏事.

我正在将一个mysql应用程序迁移到postgres …我曾经在MysqL-land中遵循这样的模式将连接表记录添加到DB:

class EventsSeries < ActiveRecord::Base
  #  UNIQUE KEY `index_events_series_on_event_id_and_series_id` (`event_id`,`series_id`)
  belongs_to :event
  belongs_to :series
end

class Series < ActiveRecord::Base

  has_many :events_series
  before_validation :add_new_event

private

  def add_new_event
    # boils down to something like this
    EventSeries.new.tap do |es|
      es.event_id = 1
      es.series_id = 1
      begin
        es.save!
      rescue ActiveRecord::RecordNotUnique
        # Great it exists
        # this isn't really a problem
        # please move on
      end
    end
  end
end

像这样调用

Series.first.save 
# should not blow up on duplicate join record,cause i don't care

然而,postgres在这上面爆发了.这里有一个很好的解释:

http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

…在“异常处理和回滚”部分(请参阅警告)

基本上#save启动一个事务,并且重复记录插入导致数据库异常,这使#saving的事务无效,这是悲伤的.

有没有更好的模式可以用于postgres-land?

谢谢!

编辑:

我坚信将这个逻辑保留在Series的保存事务中是有意义的……模式看起来像这样:

s = Series.new
s.new_event_id = 123 # this is just an attr_accessor
s.save # callbacks on Series kNow how to add the new event.

…它使我的控制器超小.

解决方法

如果您在事务内部并且要从错误中恢复并避免使整个事务无效,则必须使用保存点.

当您使用命令SAVEPOINT some-label时,您可以稍后运行命令ROLLBACK TO SAVEPOINT some-label以返回到事务中的该状态,并忽略保存点获取后的所有操作(包括错误).

请在Continuing a transaction after primary key violation error查看我的其他答案,以获得更多解释.

相关文章

项目需要,有个数据需要导入,拿到手一开始以为是mysql,结果...
本文小编为大家详细介绍“怎么查看PostgreSQL数据库中所有表...
错误现象问题原因这是在远程连接时pg_hba.conf文件没有配置正...
因本地资源有限,在公共测试环境搭建了PGsql环境,从数据库本...
wamp 环境 这个提示就是说你的版本低于10了。 先打印ph...
psycopg2.OperationalError: SSL SYSCALL error: EOF detect...