As part of registering a new user; we assign them a resource (a Solr core, in this case) from a precompiled list (a table).
If 5 users sign up, they must be assigned 5 different cores; if the user successfully registers, the assignment is made final (see my depiction below).
But in real world, concurrently registering new users contend for the same row, not choose different rows. If X needs 5 seconds to register, Y and Z's registrations which are in X's "duration" will fail as they contend for the same row by X.
Question: How to make transactions choose without contentions, even under high concurrency such as 100 signups a second?
table: User
user_id name core
1 Amy h1-c1
2 Anu h1-c1
3 Raj h1-c1
4 Ron h1-c2
5 Jon h1-c2
table: FreeCoreSlots
core_id core status
1 h1-c1 used
2 h1-c1 used
3 h1-c1 used
4 h1-c2 used
5 h1-c2 used #these went to above users already
6 h1-c2 free
7 h1-c2 free
8 h1-c2 free
9 h1-c2 free
Pseudo-code if stuff was isolated:
sql = SQLTransaction()
core_details = sql.get("select * from FreeCoreSlots limit 1")
sql.execute("update FreeCoreSlots set status = 'used' where id = {id}".format(
id = core_details["id"]))
sql.execute("insert into users (name,core) values ({name},{core})".format(
name = name,
id = core_details["id"]))
sql.commit()
If 100 signups happen a second, they would contend for the first row in FreeCoreSlots
and cause serious fails.
There is a select... for update as in InnoDB SELECT ... FOR UPDATE statement locking all rows in a table as the solution, but they seem to suggest lowering the isolation. Is this method the right way?