views:

293

answers:

2

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?

+1  A: 

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

Eric Petroelje
+1  A: 

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.

txyoji
But there CAN be multiple 1's in user_id row but each will belong to a different user. Just like there can be multiple Bob's but each will have different user_id
Chad
This won't prevent that. Its a composite key made up of both user_id and name.It prevents a duplicate user_id/name combination from being entered.So 1/bob, 1/sue, 2/bob are ok. Putting in another 1/bob will cause a database error.
txyoji
great, thanks for that hint, it was just what I needed.
Chad