【发布时间】:2017-11-13 05:40:01
【问题描述】:
我目前在我的计算机上运行 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 服务器返回的 TRANSACTION ISOLATION LEVEL:
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 是TRANSACTION_REPEATABLE_READ 的常量documented,如下所示:
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.
我想看看这种行为,所以我有 2 个主要方法,第一个是:
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 进程应该锁定该行。
我缺少什么以及如何锁定这一行?
【问题讨论】:
标签: java mysql sql jdbc locking