Question

I have an InnoDB table containing users, like this:

+--------------+-----------------------+
| user_id      | name                  |
+--------------+-----------------------+
| 1            | Bob                   |
| 1            | Marry                 |
| 2            | Bob                   |
| 1            | John                  |
| 3            | Bob                   |
| 2            | Marry                 |
+--------------+-----------------------+

On each insert I increment user_id by 1 so for example, the next user_id for Bob will be 4

I use this query to do that:

INSERT INTO users (user_id, name)
SELECT 1 + coalesce((SELECT max(user_id) FROM users WHERE name='Bob'), 0), 'Bob';

Now I need to make sure that two different users don't add a 'Bob' at the same time. I don't want any two Bobs with user_id 4. Each of Bob's user ids must be different.

Is is possible to write and update lock all of Bob's rows when the above insert query is run? I cannot lock the whole table because many other users still need full access to their rows. Also, all rows should be readable at all times. How would I do this?

Was it helpful?

Solution

Assuming InnoDB here, you can use SELECT ... LOCK IN SHARE MODE to lock the rows when you select them.

OTHER TIPS

To solve the first part of your question, create a unique index on user_id and name.

alter table `users` add unique index ak_user_id_name(user_id,name);

That will prevent duplicate user_id,name records.

The answer to this question is the same as this one. InnoDB will lock more rows here than you expect for safety with statement-based binary logging.

The solution: use row based binary logging with the read-committed isolation level.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top