Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
857 views
in Technique[技术] by (71.8m points)

sql - How to avoid race condition in MySQL

I've got a potential race condition in an application I'm developing, which I'd like to account for and avoid in my querying.

To summarise the application flow...

  1. Create a new row in the entries table:

    INSERT INTO entries ( name, email ) VALUES ( 'Foo Bar', 'foo@example.com' );

  2. Find out if Mr Bar is a winner by checking a time-sensitive prizes table:

    SELECT id FROM prizes WHERE various_time_conditions = 'met' AND id NOT IN ( SELECT prize_id FROM entries );

  3. If he's a winner, update his entry row accordingly:

    UPDATE entries SET prize_id = [prize id] WHERE id = [entry id];

As each prize can only be given out once, I need to eliminate any possibility of a race condition where another process can query the prizes table and update the entry table between steps 2 and 3 above.

I've been doing some research and have found a load of information about transactions (all my tables use InnoDB) and using MySQL's SELECT ... FOR UPDATE syntax but I'm confused as to which is the most suitable solution for me.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You're going to want to lock the prize record. So add some availability flag on the prizes table (perhaps with a default value) if you're not going to use something like a winner_id. Something like this:

SELECT id FROM prizes WHERE ... AND available = 1 FOR UPDATE

Then set the availability if you do assign the prize:

UPDATE prizes SET available = 0 WHERE id = ...

You'll need to wrap this inside a transaction of course.

Make sure that every time you check to see if the prize is available, you add AND available = 1 FOR UPDATE to the query because a SELECT without the FOR UPDATE is not going to wait for a lock.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...