Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to atomically claim a row or resource using UPDATE in mysql

i have a table of resources (lets say cars) which i want to claim atomically. I then want information about which resource I just claimed.

If there's a limit of one resource per one user, i can do the following trick:

UPDATE cars SET user = 'bob' WHERE user IS NULL LIMIT 1
SELECT * FROM cars WHERE user = 'bob'

This way, I claim the resource atomically and then I can see which row I just claimed.

This doesn't work when 'bob' can claim multiple cars. I realize I can get a list of cars already claimed by bob, claim another one, and then SELECT again to see what's changed, but that feels hackish.

What I'm wondering is, is there some way to see which rows I just updated with my last UPDATE?

Failing that, is there some other trick to atomically claiming a row? I really want to avoid using SERIALIZABLE isolation level. If I do something like this:

1 SELECT id FROM cars WHERE user IS NULL
2 <here, my PHP or whatever picks a car id>
3 UPDATE cars SET user = 'bob' WHERE id = <the one i picked>

would REPEATABLE READ be sufficient here? In other words, could I be guaranteed that some other transactions won't claim the row my software has picked during step 2?

like image 238
Igor Serebryany Avatar asked Mar 17 '10 08:03

Igor Serebryany


People also ask

How do I UPDATE an entire row?

To update an entire row in MySQL, use UPDATE command. You need to know the primary key column. The syntax is as follows to update an entire row.

What is the query for UPDATE in MySQL?

The MySQL UPDATE query is used to update existing records in a table in a MySQL database. It can be used to update one or more field at the same time. It can be used to specify any condition using the WHERE clause.


1 Answers

UPDATE cars SET user = 'bob' WHERE id = 123 AND user IS NULL;

The update query returns the number of changed rows. If it has not updated any, you know the car has already been claimed by someone else.

Alternatively, you can use SELECT ... FOR UPDATE.

like image 80
Sjoerd Avatar answered Oct 15 '22 15:10

Sjoerd