Advertisement
Guest User

Untitled

a guest
Sep 8th, 2017
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.01 KB | None | 0 0
  1. import java.sql.Connection;
  2. import java.sql.DriverManager;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.sql.Statement;
  7.  
  8. import org.h2.tools.DeleteDbFiles;
  9.  
  10.  
  11. /**
  12.  *
  13.  */
  14.  
  15. public class MvccConflictVisibilityThreaded {
  16.     public static final DB db = DB.H2;
  17.    
  18.     enum DB {
  19.         H2("create table test(id int identity primary key, val int not null, unique(val))"),
  20.         PG("create table test(id serial primary key, val int not null, unique(val))"),
  21.         MY("create table test(id int primary key auto_increment, val int not null, unique(val)) type=innodb"),
  22.         ;
  23.        
  24.         private final String tableString;
  25.  
  26.         private DB(String tableString) {
  27.             this.tableString = tableString;
  28.         }
  29.        
  30.         public Connection getConnection() throws SQLException {
  31.             switch (this) {
  32.                 case H2:
  33.                     return DriverManager.getConnection("jdbc:h2:~/test;MVCC=TRUE");
  34.                 case PG:
  35.                     return DriverManager.getConnection("jdbc:postgresql://localhost:5432/test", "test", "test");
  36.                 case MY:
  37.                     return DriverManager.getConnection("jdbc:mysql://localhost/test", "test", "test");
  38.             }
  39.             throw new IllegalStateException("Unknown type: " + this);
  40.         }
  41.  
  42.         public String getTableString() {
  43.             return this.tableString;
  44.         }
  45.        
  46.     }
  47.    
  48.     public static Connection getConnection() throws SQLException {
  49.         return db.getConnection();
  50.     }
  51.    
  52.     public static class FirstInserter extends Thread {
  53.         public void run() {
  54.             try {
  55.                 Connection conn = getConnection();
  56.                 conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
  57.                 conn.setAutoCommit(false);
  58.                 PreparedStatement insert = conn.prepareStatement("insert into test (val) values (?)");
  59.                 insert.setInt(1, 42);
  60.                 insert.execute();
  61.                 Thread.sleep(3000);
  62.                 conn.commit();
  63.                 conn.close();
  64.             } catch (Exception e) {
  65.                 e.printStackTrace();
  66.             }
  67.         }
  68.     }
  69.    
  70.     public static class SecondInserter extends Thread {
  71.         public void run() {
  72.             try {
  73.                 Connection conn = getConnection();
  74.                 PreparedStatement retr0 = conn.prepareStatement("select id from test where val = ?");
  75.                 PreparedStatement retr1 = conn.prepareStatement("select id from test where val = ?");
  76.                 PreparedStatement retr2 = conn.prepareStatement("select id from test where val = ?");
  77.                 conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
  78.                 conn.setAutoCommit(false);
  79.                 PreparedStatement insert = conn.prepareStatement("insert into test (val) values (?)");
  80.                 insert.setInt(1, 42);
  81.                 retr0.setInt(1, 42);
  82.                 retr1.setInt(1, 42);
  83.                 retr2.setInt(1, 42);
  84.                 // Make sure this execute happens after the first one, but before
  85.                 // the commit of the first one()
  86.                 Thread.sleep(1500);
  87.                 try {
  88.                     ResultSet rs = retr0.executeQuery();
  89.                     if (rs.next()) {
  90.                         System.out.println("Unexpected found: " + rs.getInt(1));
  91.                     } else {
  92.                         // expected, not committed yet
  93.                         System.out.println("Did not find yet as expected.");
  94.                     }
  95.                     insert.execute();
  96.                     conn.commit();
  97.                 } catch (SQLException e) {
  98.                     // assume unique constraint violation
  99.                     conn.rollback();
  100.                     ResultSet rs = retr1.executeQuery();
  101.                     if (rs.next()) {
  102.                         System.out.println("Recovered: " + rs.getInt(1));
  103.                     } else {
  104.                         System.out.println("Could not recover!");
  105.                     }
  106.                     rs.close();
  107.                     // wait for the commit to happen
  108.                     Thread.sleep(2000);
  109.                     conn.rollback();
  110.                     // retr1 seems to cache the result of the previous execution,
  111.                     // which now is an incorrect value since the other thread
  112.                     // committed, use retr2 instead
  113. //                    rs = retr1.executeQuery();
  114. //                    if (rs.next()) {
  115. //                        System.out.println("Recovered AFTER commit: " + rs.getInt(1));
  116. //                    } else {
  117. //                        System.out.println("Could not recover after commit!");
  118. //                    }
  119.                     rs = retr2.executeQuery();
  120.                     if (rs.next()) {
  121.                         System.out.println("Recovered separate statement: " + rs.getInt(1));
  122.                     } else {
  123.                         System.out.println("Could not recover separate statement!");
  124.                     }
  125.                     rs.close();
  126.    
  127.                 }
  128.                 conn.close();
  129.             } catch (Exception e) {
  130.                 e.printStackTrace();
  131.             }
  132.         }
  133.     }
  134.    
  135.    
  136.     /**
  137.      * @param args
  138.      */
  139.     public static void main(String[] args) throws Exception {
  140.         // delete the database named 'test' in the user home directory
  141.         DeleteDbFiles.execute("~", "test", true);
  142.  
  143.         Class.forName("org.h2.Driver");
  144.         Class.forName("org.postgresql.Driver");
  145.         Class.forName("com.mysql.jdbc.Driver");
  146.        
  147.         Connection conn = getConnection();
  148.         Statement stat = conn.createStatement();
  149.         stat.execute("drop table if exists test");
  150.         stat.execute(db.getTableString());
  151.         conn.close();
  152.        
  153.         new FirstInserter().start();
  154.         new SecondInserter().start();
  155.        
  156.        
  157.     }
  158.  
  159. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement