2017-02-10 9 views
1

私は 'phantom read'でコードを書いています。アイソレーションレベルがシリアライズ可能でない場合、私のコードは異なる値を出力するはずですが、 'repeatable read'アイソレーションレベルがあり、シリアライズ可能です。同じ数字が表示されますが、2番目に大きい数字が表示されます。なぜそうなのか?私は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の文書https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.htmlによると、 'phantom reads'からのシリアライズ可能な保存のみです。だから、なぜ反復可能な読み取りレベルを 'phanotom read'から保存するのですか? MySQL docsから

+0

怖いウォンバット - 反復は、反復可能で読み取る扱う、ファントムを扱うserialisableがhttps://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html –

+0

がhttp://stackoverflow.comを見る読み込み読み込み/ a/11044968/2310289 –

答えて

1

(約REPEATABLE READ):

一貫性は同じトランザクション内で読み込みは、最初の読み取りによって確立されたスナップショット をお読みください。

Consistent reads

Aに関係なく同時に実行 他のトランザクションによって実行された変更の、時点に基づいてクエリ 結果を提示するために、スナップショット情報を使用して操作を読み取ります。

自動コミットをfalseに設定すると、両方の選択が同じトランザクションで実行されることを意味します。だから、あなたの懸念は何ですか?それが期待されるように動作するように見えます。

も注意this remark:

デフォルトREPEATABLE READ分離 レベルで実行されていることとします。一貫性のある読み取り(つまり、通常のSELECT 文)を発行すると、InnoDBはクエリにデータベースが表示される に従ってトランザクションにタイムポイントを与えます。別のトランザクションで 行が削除され、タイムポイントが割り当てられた後にコミットすると、 行が削除されたとは見なされません。挿入と更新は同様に扱われます。

+0

私はこれが** I ** expectとして動作することに同意しますが、それらは異なる 'connections'であるので、私はそれらが異なるtranactionであると仮定します。トランザクションの途中で2つの同一のクエリが実行され、2番目のクエリによって返された行のコレクションが返されると、ファントムの読み取りが行われます(例:phantom read/a11044968/2310289)。 * –

+1

これは間違いなく異なるトランザクションです。この影響について言われることはすべて、さまざまな取引の状況に属します。具体的なRDMSを使用する場合は、最終的な動作がDBによって決定されるため、共通のJDBC記述ではなく、このDBのドキュメントに頼る方がよいでしょう。 – Andremoniy

+0

'REPEATABLE READ' *ファントム行を持つことが必ずしもファントム行を持っていなければならないということを意味するわけではありません。 InnoDBの次のキー/ギャップロックは、ここでの要因かもしれません。 https://dev.mysql.com/doc/refman/5.7/en/innodb-next-key-locking.html私はこの答えに同意し、観察された動作は必ずしも間違っているとは限りません。 –

関連する問題