GORM Playground Link

https://github.com/go-gorm/playground/pull/536

Description

Calling FirstOrCreate from multiple gouroutines for the same object results in a UNIQUE constraint failed error.

Note

Maybe FirstOrCreate is not supposed to be safe by choice, i couldn't find any mention of that except this https://github.com/go-gorm/gorm/issues/2760, if it is by design maybe mention that in the documentation? i found in v1 docs that "GORM is safe for concurrent use by multiple goroutines."

Comment From: a631807682

Errors can occur as long as the operation is not atomic for database, it has nothing to do with thread safety. The database may be changed by any process, you need to avoid it by locking.

Refer to the following pseudo code:

  app1.Find
  app2.Delete
  app1.Update // throw err, record has been deleted

For gorm you can use OnConflict but it won't solve all problems.

tx := DB.Clauses(clause.OnConflict{
        UpdateAll: true,
})
tx.FirstOrCreate(&languageCopy)

Comment From: YeahItsMeAgain

Seems i wasn't descriptive enough 😅 I was talking about the exact situation that i had written in my test, that an orm like django's solves with this logic (full code here):

try:
    return self.get(**params)
except self.model.DoesNotExist:
    try:
        with transaction.atomic(using=self.db):
            return self.create(**params)
    except IntegrityError:
        try:
            return self.get(**params)
        except self.model.DoesNotExist:
            pass
        raise

But after rethinking about it i suppose [locking the relevant pieces of code\using OnConflict to upsert relevant columns\handling the error in other ways] is much better and safer! thx :)