Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to produce phantom reads?

Tags:

Using "repeatable read" it should be possible to produce a phantom read, but how? I need it for an example teaching CS-students.

I think that I must make a "SELECT ... WHERE x<=888" on a non-indexed field x, with an upperlimit 888 not present, and then on another connection insert a new row with a value just below 888.

Except it doesn't work. Do I need a very large table? Or something else?

like image 974
Erik Avatar asked Mar 26 '11 19:03

Erik


People also ask

What are phantom reads?

A Phantom read occurs when one user is repeating a read operation on the same records, but has new records in the results set: READ UNCOMMITTED. Also called a Dirty read. When this isolation level is used, a transaction can read uncommitted data that later may be rolled back.

How do you solve a phantom read?

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.

What is a phantom read in SQL?

A phantom read occurs when, in the course of a transaction, new rows are added or removed by another transaction to the records being read. This can occur when range locks are not acquired on performing a SELECT … WHERE operation.

Why is Phantom read a problem?

Phantom Read Problem: The phantom read problem occurs when a transaction reads a variable once but when it tries to read that same variable again, an error occurs saying that the variable does not exist.


1 Answers

The "phantom read" in MySQL on RR isolation level is hidden deep, but still can reproduce it. Here are the steps:

  1. create table ab(a int primary key, b int);

  2. Tx1:
    begin;
    select * from ab; // empty set

  3. Tx2:
    begin;
    insert into ab values(1,1);
    commit;
  4. Tx1:
    select * from ab; // empty set, expected phantom read missing.
    update ab set b = 2 where a = 1; // 1 row affected.
    select * from ab; // 1 row. phantom read here!!!!
    commit;
like image 107
ColinBinWang Avatar answered Sep 24 '22 12:09

ColinBinWang