Say I've got the tables users
, teams
and a teams_users
junction table (team_ID
, user_ID
/ composite PK). If I wanted to add a user to a team, what's the best option when it comes to performance / concurrency issues?
Option 1)
First query the table and see if the relationship already exists, if it does just notify the user that made the request.
Option 2)
While inserting, use the WHERE EXISTS
syntax (2nd example).
Option 3)
Use Postgres 9.5 Beta for the UPSERT functionality. (I suppose using a Beta version for a school project isn't that bad of an idea?).
What option would be best when it comes to concurrency. I'm not very experienced with SQL (just the standard stuff for CRUD applications). But as far as I know, in the first option, a relationship could be inserted by another user right after querying the junction table but before actually inserting a relation myself. I suppose there won't be any duplicates because I've got a composite primary key in that junction table, but I feel like it's bad practice to just let it make the exception and continue. Furthermore, in my current code, I'd return a 500 http status in this case (because of a db exception), which doesn't really seem right.
I've read I could partially solve the above by 'locking' the database/table, but I don't know if that's the right method.
Finally, I have no idea if there's a race condition when it comes to the 2nd option.
Best Answer
For just
INSERT INTO teams_users ...
and without raising an exception, the answer is option 3: Use Postgres 9.5 Beta for the UPSERT functionality. For a "school project" this is the best option anyway. Your students will want to study the latest version.Where
teams_users_pkey
is the actual name of your PK constraint.This inserts the new row or does nothing if the unique index would raise a duplicate key violation. Designed to be fast and safe against concurrent writes.
Additional question
Option 2 being:
That would actually be
WHERE NOT EXISTS
in your case and yes, there is a race condition. Two parallel transactions could find that a certain combination does not exist yet at virtually the same time and happily try to insert it. The slower one would run into a unique violation and error out. Not much of a problem if your application is prepared for that eventuality.