I think you need a unique index if you're doing something like this in MS-SQL, Postgres, or MySQL. Otherwise, the default isolation level won't prevent this data race:
writer A: begin xact, update, see 0 rows updated
writer B: begin xact, insert same thing, end xact
writer A: insert, end xact
One reason I use ON CONFLICT in Postgres is for explicitness. You're specifically telling the DBMS to upsert, and it'll throw an error if you don't have a unique index to support this.
That's how I got an improved query performance for syncing data.