Let’s consider having two functions:
increment(x) which increments a value x
retrieve(x) which retrieves a value x
Now let’s have two subjects (processes, threads, users) which use both functions
in order to increment the value and then retrieve it. I will give a real-life example
1. no race condition:
1. A: increment(x) //x=6
2. A: retieve(x) //A.x = 6
3. B: increment(x) //x=7
4. B: retieve(x) //B.x = 7
Let x be 5 before the first operation. After step 2 x holds the value 6 and
A has the correct value. After step 4 x holds the value 7 and B has also the correct
value. However let’s look at another scenario now:
2. race condition:
1. A: increment(x) //x=6
2. B: increment(x) //x=7
3. A: retrieve(x) //A.x=7
4. B: retrieve(x) //B.x=7
Now both subjects have the value 7. This problem is called a race condition as the result
depends on what subject is first and both do not know about the operations of the other.
You might think of that as a very theoretical problem, but it’s not:
Consider the following simple PHP code snippet. Let’s have
a table ‘table’ with the fields id, val1, val2. Let us INSERT a row into db and retrieve
the given id (using MySQL’s ‘auto_increment’ option) afterwards (we might use it for data
You may have identified the possible race condition immediately: What happens if two subjects
(i.e. two users/threads) are using the script at exactly the same time?
You guessed it - if another INSERT happens to be executed right after the first INSERT, the
retrieved id will be wrong for the first subject.
However there is a very easy workaround for this problem (we will have to disable the auto_increment
$success = false;
$result = mysql_query(“SELECT MAX(id) FROM table”);
$id = mysql_result($result,0,0);
$success = mysql_query(“SELECT MAX(id) FROM table”);
mysql_query(“INSERT INTO table (id, val1, val2) VALUES($id,$val1,$val2)”);
The while-loop is executed until $success will be ‘true’. It is set to ‘true’ whenever the
INSERT INTO table (id, val1,val2) succedes and it only succedes, when the id, that was ‘guessed’
by the SELECT MAX(id) query, was not used before (of course considering the id being a unique primary key).
Please notice, that mysql_result($result,0,0) might return NULL if the table is empty, however this is
no problem at all as PHP is everything else than a type safe language, so $id=NULL; $id++; leads to $id being 1.
One might think that these race conditions are less likely to happen. But even if they are unlikely we should
care about all those eventualities.
blog comments powered by Disqus