SelectOrInsert is not safe for transactions
tbarbugli opened this issue · 0 comments
tbarbugli commented
Say that you have something like this:
db.RunInTransaction(ctx, func(tx *pg.Tx) error {
inserted, err := tx.Model(). SelectOrInsert()
})
if this code runs concurrently you will get a transaction aborted error instead of a nil error. This happens because SelectOrInsert does this inside of a retry loop:
if err != nil {
insertErr = err
if err == internal.ErrNoRows {
continue
}
if pgErr, ok := err.(internal.PGError); ok {
if pgErr.IntegrityViolation() {
continue
}
if pgErr.Field('C') == "55000" {
// Retry on "#55000 attempted to delete invisible tuple".
continue
}
}
return false, err
}
which is OK unless you are doing this inside a transaction, the moment you hit an error the transaction will be aborted and the next SELECT will error.