So my app needs to let users generate random alphanumeric codes like A6BU31, 38QV3B, R6RK7T. Currently they consist of 6 chars, whereas I and O are not used (so we got 34^6 possibilities). These codes are then printed out and used for something else.
I must now ensure that many users can “reserve” up to 100 codes per request, so user A might want to get 50 codes, user B wants to generate 10 and so on. These codes must be unique across all users, so user A and user B may not both receive the code ABC123.
My current approach (using PHP and MySQL) is to have two InnoDB tables for this:
- One (the “repository”) contains a large list of pre-generated codes (since the possibility of collisions will increase over time and I do not want to go the try-insert-if-fails-try-another-code approach). The repository contains just the codes and an auto-incremented ID (so I can sort them, see below).
- The other table holds the reserved keys (i.e. code + owning user).
Whenever a user wants to reserve N keys, I planned to do the following
BEGIN;
INSERT INTO revered_codes (code,user_id)
SELECT code FROM repository WHERE 1 ORDER BY id LIMIT N;
DELETE FROM repository WHERE 1 ORDER BY id LIMIT N;
COMMIT;
This should work, but I’m not sure. It seems like I’m building a WTF solution.
After insertion I must select the just reserved codes to display them to the user. And that’s the tricky part, since I don’t really know how to identify the just reserved codes after my transaction is done. I could of course add just another column to my reserved_codes table, holding some kind of random token, but this seems even more WTFy.
My favorite solution would be to have a random number sequence, so that I can just perform INSERT operations in the reserved_codes table.
So, how to do this unique, random and transactional-safe sequence in MySQL? One idea was to have a regular auto-increment on the reserved_codes table and derive the random code value from that numeric column, but I was wondering whether there was a better way.
UPDATE: I forgot to mention that it would be advantagous to have a rather small table of reserved codes, as I later have to find single codes again for updating them (reserved_codes has a couple of more attributes to it). So letting the reserved table grow slowly is good (instead of having a huge index over ~1mio pre-generated codes).
If you already have a repository table, I would just add a user column and then run this query:
Afterwards, you can select the records again. This had two distinct disadvantages:
user_id