2

I've wrote code with 'phantom read' and my code should print different values if isolation level not serializable, but I have 'repeatable read' isolation level and it works like serializable. It shows me same digits, but should second time show bigger digit. Why so? I've MySql Database. Here my Example:

public class PhantomReadLesson {
static String url = "jdbc:mysql://localhost:3306/Lessons";
static String username = "root";
static String password = "1";
public static void main(String[] args) throws SQLException, InterruptedException {
    try(Connection conn = DriverManager.getConnection(url, username, password);
        Statement statement = conn.createStatement()) {
        conn.setAutoCommit(false);
        conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
        ResultSet rs = statement.executeQuery("Select count(*) from Books");
        while(rs.next()){
            System.out.println(rs.getInt(1));
        }
        new OtherTransaction2().start();
        Thread.currentThread().sleep(1000);
        rs = statement.executeQuery("Select count(*) from Books");
        while(rs.next()){
            System.out.println(rs.getString(1));
        }
    }
}

static class OtherTransaction2 extends Thread {
    @Override
    public void run() {
        try(Connection conn = DriverManager.getConnection(url, username, password);
            Statement stmt = conn.createStatement()) {
            conn.setAutoCommit(false);
            conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
            stmt.executeUpdate("insert into Books (name) VALUES ('new Row')");
            conn.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
}

I'm imitating 'phantom reads' in here. If I use 'repeatable_read' or 'serializable' levels it show the same numbers, if use 'read_commmited' or 'read_uncomited' levels it will show different numbers. But according to java doc https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html only serializable save from 'phantom reads'. So why repeatable read level save from 'phanotom read'?

Max Husiv
  • 305
  • 1
  • 4
  • 12
  • Scary Wombat - Repeatable reads dealing with Repeatable reads, serialisable dealing with phantom reads https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html – Max Husiv Feb 10 '17 at 00:57
  • see http://stackoverflow.com/a/11044968/2310289 – Scary Wombat Feb 10 '17 at 01:02

1 Answers1

1

From MySQL docs (about REPEATABLE READ):

Consistent reads within the same transaction read the snapshot established by the first read.

Consistent reads:

A read operation that uses snapshot information to present query results based on a point in time, regardless of changes performed by other transactions running at the same time.

As you set up auto-commit to false that means that both select's are performed in same transaction. So, what's your concerns? Looks like it works as it expected to be.

Notice also this remark:

Suppose that you are running in the default REPEATABLE READ isolation level. When you issue a consistent read (that is, an ordinary SELECT statement), InnoDB gives your transaction a timepoint according to which your query sees the database. If another transaction deletes a row and commits after your timepoint was assigned, you do not see the row as having been deleted. Inserts and updates are treated similarly.

Andremoniy
  • 34,031
  • 20
  • 135
  • 241
  • I agree that this works as **I** expect, but as they are different `connections` then I would assume that they are different tranactions. As per [link](http://stackoverflow.com/a/11044968/2310289) *A phantom read occurs when, in the course of a transaction, two identical queries are executed, and the collection of rows returned by the second query is different from the first.* – Scary Wombat Feb 10 '17 at 01:05
  • 1
    They are definitely different transactions. Everything which is said about this effects belongs to situation with different transactions. When you work with concrete RDMS it is better rely on this DB documentation rather on common JDBC description, because end behaviour determines by DB. – Andremoniy Feb 10 '17 at 01:08
  • `REPEATABLE READ` *can* have phantom rows does not necessarily mean it *must* have phantom rows. InnoDB next-key/gap locks might be a factor here. https://dev.mysql.com/doc/refman/5.7/en/innodb-next-key-locking.html I agree with this answer, the observed behavior isn't necessarily wrong. – Michael - sqlbot Feb 10 '17 at 04:14