改为已启用 隔离级别不工作

问题描述 投票:0回答:1

我想了解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);

有两个线程 t1t2. t1 应该是 更新 数据库中的银行账户行,以及 t2 应该是 阅读 其平衡。

情况是这样的。t1 启动,打开一个连接,进行更新和 不犯. 它引发了 t2睡觉 3秒。

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

然后 t1 饰演者 承诺 更新和程序结束。

我希望发生的是 t2 受阻 t1 已完成承诺,因为 t2 正在访问同一银行账户行(t1 应该锁定该行进行更新)。) 因此。t2 应该打印的是490号银行账户的最新余额,而不是之前的。

为什么不 t1 为什么不 t2 被屏蔽了?需要注意的是 隔离度 设置为 TRANSACTION_READ_COMMITTED.

java multithreading jdbc rdbms isolation-level
1个回答
1
投票

t2中的select语句没有被阻塞,因为它只是试图读而不是写。如果你试图执行更新(或选择...进行更新),那么如果你的超时设置为等待一段时间后才放弃,它可能会被阻塞。你没有提到你使用的是哪个数据库,但这里有一些关于Postgres如何处理锁定的漂亮文档。https:/www.postgresql.orgdocscurrentexplicit-locking.html

© www.soinside.com 2019 - 2024. All rights reserved.