Java 如何使用JDBC/MySQL查看事务可重复读取?

Java 如何使用JDBC/MySQL查看事务可重复读取?,java,mysql,sql,jdbc,locking,Java,Mysql,Sql,Jdbc,Locking,我的计算机上目前正在运行MySQL服务器(5.7.16),在该服务器上名为“Sakila”的数据库中有以下示例行: mysql> SELECT * FROM actor WHERE last_name = 'tugay'; +----------+------------+-----------+---------------------+ | actor_id | first_name | last_name | last_update | +----------+---

我的计算机上目前正在运行MySQL服务器(5.7.16),在该服务器上名为“Sakila”的数据库中有以下示例行:

mysql> SELECT * FROM actor WHERE last_name = 'tugay';
+----------+------------+-----------+---------------------+
| actor_id | first_name | last_name | last_update         |
+----------+------------+-----------+---------------------+
|      201 | koray      | tugay     | 2017-06-11 21:42:08 |
+----------+------------+-----------+---------------------+
这是JDBC为my MySQL服务器返回的事务隔离级别:

public static void main(String[] args) throws SQLException, InterruptedException {
    final Connection connection = getConnection("jdbc:mysql://localhost:3306/sakila", "root", "root");
    System.out.println(connection.getTransactionIsolation()); // Prints 4!
    connection.close();
}
其中
4
这里是
事务可重复读取的常量,如下所示:

int TRANSACTION_REPEATABLE_READ  = 4;
A constant indicating that dirty reads are prevented. 
This level prohibits a transaction from reading a row with uncommitted changes in it.
我想看到这种行为,所以我有两种主要方法,第一种是:

import java.sql.*;

import static java.sql.DriverManager.*;

public class Foo {

    public static void main(String[] args) throws SQLException, InterruptedException {
        final Connection connection = getConnection("jdbc:mysql://localhost:3306/sakila", "root", "root");
        connection.setAutoCommit(false);

        final Statement statement = connection.createStatement();
        statement.executeUpdate("UPDATE actor SET first_name = 'ALTERED' WHERE first_name = 'koray'");

        System.out.println("Sleeping!");

        // Here I am expecting MySQL to lock the Row so no other Connection
        // can read data from it. This row will be updated, so unless the transaction is 
        // either commited or rolled back, the read data will be 'dirty'.
        Thread.sleep(5000);

        connection.commit();
        connection.close();
    }
}
如您所见,事务在自动提交模式下是而不是,并且我正在锁定行5秒钟。在该进程处于休眠状态时,我还不断运行以下代码:

public class Bar {

    public static void main(String[] args) throws SQLException, InterruptedException {
        final Connection connection = getConnection("jdbc:mysql://localhost:3306/sakila", "root", "root");
        connection.setAutoCommit(false);

        final Statement statement = connection.createStatement();
        final ResultSet resultSet = statement.executeQuery("SELECT * FROM actor WHERE last_name = 'tugay'");

        resultSet.next();
        System.out.println(resultSet.getString("first_name"));

        connection.close();
    }
}
但即使我在控制台中看到“睡眠”文本,只要我在Bar中运行main方法,我也会看到如下值

koray
koray
koray
ALTERED
我的期望是永远不会看到koray,因为这是一个“脏数据”,第一个java进程应该锁定行


我遗漏了什么以及如何锁定此行?

您应该再次阅读定义:

此级别禁止事务读取未提交的行 它的变化


更改的是脏数据,因为它没有提交。科雷是正确的。酒吧禁止看到“涂改”。只要交易未提交,您将继续看到“koray”。

我认为这并不能回答我的问题。@KorayTugay这正是您的问题的答案。隔离级别通过向您显示更新前的值来防止您看到未提交的值。它不会阻止您看到旧的值或让您等待。行锁(一个
X
lock)确实存在,但是对于另一个要阻止它的事务,第二个事务必须尝试获取一个不兼容的锁。如果您想要描述的行为,第二个事务必须
选择。。。在共享模式下锁定(对于as
IS
锁定)或
选择。。。更新
(对于
IX
锁)。@KorayTugay你能再澄清一点吗,什么让你困惑?我想我现在明白了,在Micael的解释之后。我的期望是错误的。我的理解是“koray”是肮脏的数据,似乎“Changed”是肮脏的数据。你能看到吗@MichaelSqlbot