我用“幻读”编写代码'如果隔离级别不可序列化,我的代码应该打印不同的值,但我有可重复的读取'隔离级别,它像序列化一样工作。它显示我相同的数字,但应该第二次显示更大的数字。为什么这样?我是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'或者'可序列化的'它显示相同的数字,如果使用' read_commmited'或者' read_uncomited'它会显示不同的数字。但根据java doc https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html,只有可以序列化的“幻像读取”保存。那么为什么可重复读取级别保存来自' phanotom read'?
答案 0 :(得分:1)
来自MySQL docs(约<Google> To get test ads on this device, call: request.testDevices = @[ kGADSimulatorID ];
):
同一事务中的一致读取读取快照 由第一次阅读建立。
使用快照信息呈现查询的读取操作 结果基于某个时间点,而不管执行的更改 其他交易同时运行。
当您将自动提交设置为REPEATABLE READ
时,这意味着两个选择都在同一个事务中执行。那么,你的担忧是什么?看起来它的工作方式与预期的一样。
另请注意this remark:
假设您在默认的REPEATABLE READ隔离中运行 水平。发出一致读取时(即普通SELECT) 声明),InnoDB为您的交易提供了一个时间点 您的查询查看数据库。如果另一个事务删除a 分配您的时间点后的行和提交,您没有看到 已被删除的行。插入和更新的处理方式相似。