我的计算机上当前运行 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 返回的 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();
}
where 4
这是常数TRANSACTION_REPEATABLE_READ
这是有记录的 https://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html#TRANSACTION_REPEATABLE_READ如下:
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();
}
}
如您所见,交易是not在自动提交模式下,我锁定该行 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
我的期望是永远见不到科雷因为这是一个“脏数据”,第一个 java 进程应该锁定该行。
我缺少什么以及如何锁定这一行?