Почему уровень изоляции "Repeatable read" в java спасает меня от "Phantom reads"?

Я написал код с фантомным чтением, и мой код должен печатать разные значения, если уровень изоляции не сериализуем, но у меня есть уровень изоляции "повторяемое чтение", и он работает как сериализуемый. Он показывает мне те же цифры, но должен второй раз показать большую цифру. Почему так? У меня есть база данных MySql. Вот мой пример:

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();
        }
    }
}
}

Я подражаю "фантомному чтению" здесь. Если я использую уровни 'repeatable_read' или 'serializable', он показывает те же цифры, если я использую уровни 'read_commmited' или 'read_uncomited', он показывает разные числа. Но в соответствии с документом java https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html сохраняются только сериализуемые данные из "фантомного чтения". Так зачем повторять сохранение уровня чтения из 'phanotom read'?

1 ответ

Из документов MySQLREPEATABLE READ):

Последовательные чтения в одной и той же транзакции считывают моментальный снимок, созданный при первом чтении.

Последовательные чтения:

Операция чтения, которая использует информацию моментального снимка для представления результатов запроса на определенный момент времени, независимо от изменений, выполненных другими транзакциями, выполняющимися в то же время.

Как вы устанавливаете авто-коммит false это означает, что оба выбора выполняются в одной транзакции. Итак, что вас беспокоит? Похоже, все работает так, как ожидалось.

Обратите внимание также на это замечание:

Предположим, что вы работаете с уровнем изоляции REPEATABLE READ по умолчанию. Когда вы выполняете согласованное чтение (то есть обычный оператор SELECT), InnoDB дает вашей транзакции момент времени, в соответствии с которым ваш запрос видит базу данных. Если другая транзакция удаляет строку и фиксирует ее после того, как был назначен ваш момент времени, вы не увидите строку как удаленную. Вставки и обновления обрабатываются аналогично.

Другие вопросы по тегам