If it's possible for you (I didn't invest quite enough time to fully
understand your use case), you could have a separate table with the
serial number in a single record (or one record per number sequence if
that's needed). Then to reserve a new number you would do this within a
transaction with reasonable isolation level (e.g. read committed):
1. START TRANSACTION
2. UPDATE SER_NO_TABLE SET SER_NO = SER_NO +1 -- possibly adding WHERE
SER_NO_ID = :id_for_the_desired_ser_no_sequence
3. SELECT SER_NO FROM SER_NO_TABLE -- possibly adding WHERE SER_NO_ID =
:id_for_the_desired_ser_no_sequence
4. COMMIT;
In step 2 you will obtain a write lock on that record, which will
prevent any other transaction from also reserving a new number. In step
3 you will be guaranteed to get your newly reserved serial number, since
no other transaction will be able to update it in between.
This could probably be done within the same transaction as the one your
other work is being done, but in that case there will be a risk of
deadlock I suppose, if you do things in the wrong order, e.g. one
transaction trying to reserve new number for sequence A then sequence B,
while another transaction does it the other way: first B then A.
This scheme also avoids performance problems with selecting max - not a
good idea for large tables (meaning "many records"). You also have the
possibility, if needed, to use the same sequence across multiple tables.
For example, in the O/R framework from which I got the idea they use a
single sequence for object id:s for all tables in the entire database.
Since some classes are split up across multiple tables this does make
sense in a way.
Best of luck!
Kjell Rilbe