Let the database do what it's great at doing: efficiently store and retrieve data.
MYSQL - https://stackoverflow.com/questions/449346/mysql-auto-increm...
POSTGRES - https://stackoverflow.com/questions/2095917/sequences-not-af...
thanks!
This is the same problem as multiple threads trying to increment the same global variable. Unless there is mutual exclusion while the variable is being read/incremented there will be race conditions.
I think the only way to enforce mutual exclusion for applications would be at the database layer (or any other layer where there is 1 resource that is shared between each application peer).
Create a table with two columns:
1. auto-incrementing primary key
2. integer for the actual number you're generating, let's call it 'IDValue'
Seed the new table with a single row with IDValue set to one less than your minimum value (say 0), then use the following process to generate a new number:
1. Insert a new row into the table, with a known invalid value (e.g. -1) for IDValue (note this must not be the same as the IDValue from your initial row)
2. Get the primary key of the newly inserted row
3. Get all the rows from the table (in primary key order) with primary key < the new id. This will consist of one or more rows of prior valid values (or just the initial seed), followed by one or more rows that are either valid or invalid values (other clients may be running through this process concurrently and finishing at different times) - something like this:
Key / IDValue
61 / 1119
62 / 1120
64 / 1121
65 / -1
67 / 1123
70 / -1
71 / -1
(your row is the next one after this)
4. Your new IDValue == the last valid IDValue in that set of rows + the number of rows between that and your new row + 1 - update your row with this new value - in the above example, 1123 + 2 + 1 - i.e. 1126
5. Delete the first unbroken sequence of valid rows except for the latest one, to keep the table small but leave at least one valid IDValue (IDValues 1119 and 1120 in the above example) - just something like DELETE FROM table WHERE Id < 64 (in this case) should be safe.
The database takes care of atomically creating rows which is the tricky bit, and then you can generate your own number at your leisure regardless of gaps in the Key numbering sequence.
On the exceptional case where the user is on the clear and there is an unavoidable reason to create this beast, you create a separate numbering application, that uses database transactions that are independent from the ones of the main application and only cares about numbering. It will still have holes, but few enough that you can manually inspect every so often and explain why they happened.
But you may still need to check what the behavior is during a transaction, as you could have two requests trying to add a bunch of rows at the same time.