Java 如何使用JDBC/MySQL查看事务可重复读取?
我的计算机上目前正在运行MySQL服务器(5.7.16),在该服务器上名为“Sakila”的数据库中有以下示例行: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> 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)确实存在,但是对于另一个要阻止它的事务,第二个事务必须尝试获取一个不兼容的锁。如果您想要描述的行为,第二个事务必须选择。。。在共享模式下锁定(对于asIS
锁定)或选择。。。更新
(对于
IX
锁)。@KorayTugay你能再澄清一点吗,什么让你困惑?我想我现在明白了,在Micael的解释之后。我的期望是错误的。我的理解是“koray”是肮脏的数据,似乎“Changed”是肮脏的数据。你能看到吗@MichaelSqlbot