2017-02-10 1 views
1

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

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 doc https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html только сериализуемое сохранение с «фантомных чтений». Итак, почему повторяемый уровень чтения сохраняется с «phanotom read»?

+0

Scary Вомбат - Повторяется читает дело с повторяемым читает, serialisable дела с фантомом читает https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html –

+0

см http://stackoverflow.com/a/11044968/2310289 –

ответ

1

От MySQL docs (около REPEATABLE READ):

В соответствии читает в пределах одной и той же транзакции читать снимок , установленный в первом чтении.

Consistent reads:

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

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

Обратите внимание также this remark:

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

+0

Я согласен, что это работает как ** Я ожидаю, но поскольку они разные «соединения», я бы предположил, что они разные tranactions. Согласно [link] (http://stackoverflow.com/a/11044968/2310289) * Фантомное чтение происходит, когда в ходе транзакции выполняются два идентичных запроса и коллекция строк, возвращаемых вторым запросом отличается от первого. * –

+1

Они, безусловно, разные транзакции. Все, что говорится об этих эффектах, относится к ситуации с различными транзакциями. Когда вы работаете с конкретным RDMS, лучше полагаться на эту документацию БД, а на общее описание JDBC, потому что конечное поведение определяет БД. – Andremoniy

+0

'REPEATABLE READ' * может * иметь фантомные строки не обязательно означает, что он должен иметь фантомные строки. Здесь могут быть и другие замки/замки InnoDB. https://dev.mysql.com/doc/refman/5.7/en/innodb-next-key-locking.html Я согласен с этим ответом, наблюдаемое поведение не обязательно неверно. –

Смежные вопросы