I tried this with MySQL Server 5.5:
1) ensured that transaction isolation level is repeatable_read
2) started shell-1, started a transaction in it, then read a value through select
3) started shell-2, started a transaction in it, then read the same value through select
4) in shell-1, updated the value to value + 1 and committed
5) in shell-2, updated the value to value + 1 and committed
The value lost one of its updates and was incremented only by 1.
Now, as I understand it, RR uses shared read locks and exclusive write locks, which means that in #4 and #5 above, the transactions should have dead-locked, but that did not happen.
So either my understanding of RR is faulty, or MySQL implements RR in a different manner. So what is it?
EDIT: through a similar experiment, also confirmed that an RR transaction (t1) does not see rows inserted into the same table by another RR transaction (t2), if it does another select on that table even after t2 has committed and before t1 committing. (Here's the link to this experiment: http://www.databasejournal.com/features/mysql/article.php/3393161/MySQL-Transactions-Part-II---Transaction-Isolation-Levels.htm)
Does it mean that MySQL's RR takes care of phantom reads also?
In our example, to fix the Phantom Read Concurrency Problem let set the transaction isolation level of Transaction 1 to serializable. The Serializable Transaction Isolation Level places a range lock on the rows returns by the transaction based on the condition.
At repeatable read isolation level of postgreSQL, it uses first-updater-win strategy, so earlier transaction A which has updated X before later transaction B updates X will win if A successfully commits, then B must be rollbacked. If A failed and rolled backed, then B can commit successfully.
The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a SELECT is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.
It is the default isolation in MySQL. This isolation level allows phantom read. A Phantom read occurs when one user is repeating a read operation on the same records but has new records in the results set.
MySQL does not conform to Repeatable Read really. You can force it to do by using isolation level serializable or by putting an FOR UPDATE after your selects (look at the example below). Then the desired behaviour will be achieved. Regarding phantom reads, MySQL is actually stricter than necessary...
SELECT value FROM table WHERE id = 7 FOR UPDATE;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With