jjzjj

postgresql - Golang、postgres事务: pq: unexpected transaction status in a failed transaction

coder 2024-07-08 原文

Go:v 1.3 db: postgres 使用 lib/pq

我有一个更新 postgres 数据库的应用程序。 postgres 数据库是使用 pgbouncer 设置的。

因此,通过事件连接,我有运行插入和更新的代码。这是插入代码:

func (sitemap *SiteMapData) InsertSiteMap(dbConnection *sql.DB) (int64, error) {

tx, err := dbConnection.Begin()
if err != nil {
    l4g.Error("InsertSiteMap: could not being transaction: %v", err)
    return 0, err
}
result, err := tx.Exec("INSERT INTO sitemap (url) VALUES($1)", sitemap.Url)

if err != nil {
    if !strings.Contains(err.Error(), "duplicate key value violates unique constraint") {
        l4g.Error("sitemapdata.InsertSiteMap: error inserting new sitemap data: %v", err)
    }
    tx.Rollback()
    return 0, nil
}

resultCount, _ := result.RowsAffected()
if err := tx.Commit(); err != nil {
    l4g.Error("InsertSiteMap: could not commit transaction: %v", err)
    return resultCount, err
}
l4g.Info("InsertSiteMap: Insert with %s completed with count: %d", sitemap.Url, resultCount)
return resultCount, nil
}

当我启动应用程序时,它和更新代码一样工作正常:

func (sitemap *SiteMapData) PersistSiteMapData(dbConnection *sql.DB) (int64, error) {

baseQuery, execType := sitemap.buildUpdateQuery()

// as the number of parameters in the statement may vary the following logic is needed
var result sql.Result
var execErr error

tx, err := dbConnection.Begin()
if err != nil {
    l4g.Error("PersistSiteMap: could not being transaction: %v", err)
    return 0, err
}

switch {
case execType == NoExtraDates:
    result, execErr = tx.Exec(baseQuery, sitemap.ConsecutiveFailCount, sitemap.LastAttempt.Time,
        sitemap.Etag.String, sitemap.InternalChecksum.String, sitemap.Id)
case execType == LastGatheredOnly:
    result, execErr = tx.Exec(baseQuery, sitemap.ConsecutiveFailCount, sitemap.LastAttempt.Time,
        sitemap.Etag.String, sitemap.InternalChecksum.String,
        sitemap.LastGathered.Time, sitemap.Id)
case execType == ModifiedHeaderOnly:
    result, execErr = tx.Exec(baseQuery, sitemap.ConsecutiveFailCount, sitemap.LastAttempt.Time,
        sitemap.Etag.String, sitemap.InternalChecksum.String,
        sitemap.ModifiedHeader.Time, sitemap.Id)
case execType == BothDates:
    result, execErr = tx.Exec(baseQuery, sitemap.ConsecutiveFailCount, sitemap.LastAttempt.Time,
        sitemap.Etag.String, sitemap.InternalChecksum.String,
        sitemap.LastGathered.Time, sitemap.ModifiedHeader.Time, sitemap.Id)
}

if execErr != nil {
    tx.Rollback()
    return -1, fmt.Errorf("PersistSiteMapData Error %s: %v", baseQuery, execErr)
}

resultCount, _ := result.RowsAffected()
if err := tx.Commit(); err != nil {
    l4g.Error("PersistSiteMap: could not commit transaction: %v", err)
    return resultCount, err
}
l4g.Info("PersistSiteMapData Updated sitemap %s(%d) correctly", sitemap.Url, sitemap.Id)
return resultCount, nil
}

// buildUpdateQuery returns the update query dependent on the presence of valid datetime fields.
func (sitemap *SiteMapData) buildUpdateQuery() (string, int) {
// note: lastAttempt is not covered here as this is set immediatley prior to the retrieval attempt
nextParam := 5
execType := NoExtraDates
baseQuery := "UPDATE sitemap " +
    "SET " +
    "consecutive_fail_count = $1, last_attempt = $2, etag = $3, internal_checksum = $4"

if sitemap.LastGathered.Valid {
    baseQuery = fmt.Sprintf("%s, last_gathered = $%d", baseQuery, nextParam)
    nextParam++
    execType += LastGatheredOnly
}

if sitemap.ModifiedHeader.Valid {
    baseQuery = fmt.Sprintf("%s, modified_header = $%d", baseQuery, nextParam)
    nextParam++
    execType += ModifiedHeaderOnly
}
baseQuery = fmt.Sprintf("%s WHERE id = $%d", baseQuery, nextParam)

return baseQuery, execType
}

日志显示更新一开始是正确发生的,然后过一会儿我再次检查日志,我看到了:

pq: unexpected transaction status in a failed transaction

通过 lib/pq 代码进行跟踪,它看起来像是在调用 *sql.DB.Begin() 并且事务已在运行时发生的。

我想知道是否有人可以进一步阐明这一点?

我有点想,也许我应该专门跟踪该消息,如果我收到它,则进入一个基于时间的重试循环?或者有没有办法找到错误的交易并将其终止?

谢谢 弥敦道

最佳答案

来自 http://golang.org/pkg/database/sql/#DB.Begin :

Begin starts a transaction. The isolation level is dependent on the driver.

所以看起来 lib/pq 不能很好地处理事务的隔离。

唯一的解决方法是使用 sync.Mutex 在本地锁定事务并在他们的问题跟踪器上提交错误,因为这是一个驱动程序错误。

关于postgresql - Golang、postgres事务: pq: unexpected transaction status in a failed transaction,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25864670/

有关postgresql - Golang、postgres事务: pq: unexpected transaction status in a failed transaction的更多相关文章

  1. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  2. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  3. ruby - 分布式事务和队列,ruby,erlang,scala - 2

    我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和

  4. ruby - 使用 postgres.app 在 rvm 下要求 pg 时出错 - 2

    我正在使用Postgres.app在OSX(10.8.3)上。我已经修改了我的PATH,以便应用程序的bin文件夹位于所有其他文件夹之前。Rammy:~phrogz$whichpg_config/Applications/Postgres.app/Contents/MacOS/bin/pg_config我已经安装了rvm并且可以毫无错误地安装pggem,但是当我需要它时我得到一个错误:Rammy:~phrogz$gem-v1.8.25Rammy:~phrogz$geminstallpgFetching:pg-0.15.1.gem(100%)Buildingnativeextension

  5. ruby - 导轨 4 : column reference "updated_at" is ambiguous with Postgres - 2

    我正在尝试使用“updated_at”字段的日期时间范围查询数据库。前端在JSON数组中发送查询:["2015-09-0100:00:00","2015-10-0223:00:00"]在RailsController中,我使用以下方法将两个字符串解析为DateTime:start_date=DateTime.parse(params[:date_range_arr][0])end_date=DateTime.parse(params[:date_range_arr][1])#...@events=@events.where('updated_atBETWEEN?AND?,start_d

  6. ruby-on-rails - 如何让 datamapper 与 postgresql 数据库一起工作? - 2

    我已经找到了几个使用datamapper的示例,并且能够让它们正常工作。不过,所有这些示例都是针对sqlite数据库的。我正在尝试将数据映射器与postgresql一起使用。我将datamapper中的调用从sqlite3更改为postgres,并且我已经安装了dm-postgres-adapter。但它仍然不起作用。我还需要做什么? 最佳答案 与SQLite不同,PostgreSQL不将数据库存储在单个文件中。在你拥有createdyourdatabase之后,尝试这样的事情:DataMapper.setup:default,{:

  7. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

  8. sql - 在 Rails Console for PostgreSQL 的表中显示数据 - 2

    我找到了这样的东西:Rails:Howtolistdatabasetables/objectsusingtheRailsconsole?这一行没问题:ActiveRecord::Base.connection.tables并返回所有表但是ActiveRecord::Base.connection.table_structure("users")产生错误:ActiveRecord::Base.connection.table_structure("projects")我认为table_structure不是Postgres方法。如何列出Postgres数据库的Rails控制台中表中的所有

  9. ruby-on-rails - 在 rails 中提交后回滚事务 - 2

    保存成功后可以回滚吗?让我有一个带有属性名称、电子邮件等的用户模型。例如u=User.newu.name="test_name"u.email="test@email.com"u.save现在记录将成功保存在数据库中,之后我想回滚我的事务(不是销毁或删除)。有什么想法吗? 最佳答案 您可以通过交易来做到这一点,请参阅http://markdaggett.com/blog/2011/12/01/transactions-in-rails/例子:User.transactiondoUser.create(:username=>'Nemu

  10. ruby-on-rails - Rails 迁移中的 PostgreSQL 点类型 - 2

    我想使用PostgreSQL中的point类型。我已经完成了:railsgmodelTestpoint:point最终的迁移是:classCreateTests当我运行时:rakedb:migrate结果是:==CreateTests:migrating====================================================--create_table(:tests)rakeaborted!Anerrorhasoccurred,thisandalllatermigrationscanceled:undefinedmethod`point'for#/hom

随机推荐