以下是postgres日志

Process 10396 waits for RowShareLock on relation 17204 of database 16384; blocked by process 10377.
Process 10377 waits for ShareLock on transaction 149848948; blocked by process 10396.
Process 10396: insert into "completed_jobs" ("id", ....... "limitation_code") values ($1, ...... $22) returning "id"
Process 10377: UPDATE jobs SET status='pending', updated_at=$1 WHERE id=$2

我正在从go Lang执行此操作。因此,这是在分布式环境中。

更新是正常执行,
    _, err = tx.Exec("UPDATE jobs SET status='pending', updated_at=$1 WHERE id=$2", time.Now().UTC(), job.Id)
    if err != nil {
        log.Println(getMessagePrefix(job, nil), "Error updating job status to pending", err)
    }
    err = tx.Commit()

插入在事务内部,
tx, _ := db.Begin()
tx.Exec("UPDATE jobs SET status=$1 WHERE id=$6", status)
tx.Exec("INSERT INTO completed_jobs SELECT * FROM jobs WHERE id=$1", job.Id)
tx.Exec("DELETE FROM jobs WHERE id=$1", job.Id)
err := tx.Commit()

最佳答案

在作业队列中,我通常使用以下策略来防止多个进程尝试访问相同的作业。通常,您需要跨事务控件来处理此问题。

  • 咨询锁,它是跨事务锁定任意锁。这意味着您可以排除正在处理的作业,然后再将其返回给客户端。这也避免了未决状态要求。
  • 使用随机ID进行简短交易,以防止多个进程可能击中相同ID。如果使用索引,这也很重要,因为如果您结束了长时间运行的事务处理,则可能会在索引的顶部获得很多死元组。

  • 作业队列系统中的并发性带来许多问题。但是,这两个解决了最糟糕的问题。

    关于postgresql - 插入和更新中的Postgresql死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37725124/

    10-11 23:15
    查看更多