读取提交的隔离级别不起作用

Read Commited Isolation level not working

我正在尝试了解 ACID 隔离原则。我已经编码了这部分代码:

ExecutorService executorService = Executors.newSingleThreadExecutor();

        Runnable t2 = () -> {
            System.out.println("Thread: " + Thread.currentThread().getName());
            Connection connection;

            try {
                connection = this.iDatabaseConnector.getConnection();

                PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM mssmbank.mssmbank.bankaccounts WHERE id = ?");
                preparedStatement.setInt(1, 490);

                ResultSet resultSet = preparedStatement.executeQuery();
                resultSet.next();

                System.out.println("Result: " + resultSet.getDouble("BALANCE"));

                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        };

        Runnable t1 = () -> {
            System.out.println("Thread: " + Thread.currentThread().getName());
            Connection connection;

            try {
                connection = this.iDatabaseConnector.getConnection();
                connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
                connection.setAutoCommit(false);

                PreparedStatement preparedStatement = connection.prepareStatement("UPDATE mssmbank.mssmbank.bankaccounts " + "SET balance = ? WHERE id = ?");
                preparedStatement.setDouble(1, (new Random()).nextInt(1000));
                preparedStatement.setInt(2, 490);
                preparedStatement.executeUpdate();

                ExecutorService executorService1 = Executors.newSingleThreadExecutor();
                executorService1.execute(t2);

                Thread.sleep(3_000);

                connection.commit();
                connection.close();

                executorService1.shutdown();
                executorService1.awaitTermination(20, TimeUnit.SECONDS);
            } catch (SQLException | InterruptedException e) {
                e.printStackTrace();
            }
        };

        executorService.execute(t1);
        executorService.shutdown();
        executorService.awaitTermination(20, TimeUnit.SECONDS);

有 2 个线程,t1t2t1 应该 更新 数据库中的银行帐户行,t2 应该 读取它的余额。

场景如下:t1 启动,打开连接,进行更新,不提交。它触发 t2睡眠 3 秒。

t2 启动,打开一个连接,读取余额并打印它(基本上是旧的,因为 t1 还没有提交) 然后关闭连接。

然后 t1 通过 提交 更新完成,程序结束。

我期望发生的事情是 t2 被阻塞,直到 t1 完成提交,因为 t2 正在访问同一银行帐户行(t1 应该锁定该行以进行更新)。因此,t2 应该打印了银行账户 #490 的更新余额,而不是之前的。

为什么 t1 不锁定该行?为什么 t2 没有被屏蔽? 请注意,隔离级别 设置为 TRANSACTION_READ_COMMITTED

t2 中的 select 语句没有被阻塞,因为它只是试图读取而不是写入。如果您要尝试执行更新(或 select...for update),那么如果您的超时设置为在放弃之前等待一段时间,它可能会阻塞。您没有提到您使用的是哪个数据库,但这里有一些关于 Postgres 如何处理锁定的不错的文档: https://www.postgresql.org/docs/current/explicit-locking.html