【问题标题】:Why can I read uncommited changes?为什么我可以读取未提交的更改?
【发布时间】:2021-06-27 22:03:47
【问题描述】:

我有两个简单的方法。首先 - 在表中写入一个新的 Person,但不提交更改。 第二 - 读取表中所有人的姓名。

为什么我的第二种方法能够读取未提交的更改,尽管我有 TRANSACTION_READ_COMMITTED?

public class Base {
    private static final String URL= "jdbc:postgresql://localhost:5432/postgres";
    private static final String USERNAME = "postgres";
    private static final String PASSWORD = "12345";

    private static Connection connection;
    static {
        try {
            Class.forName("org.postgresql.Driver");
            connection = DriverManager.getConnection(URL,USERNAME,PASSWORD);
            connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
            connection.setAutoCommit(false);

        } catch (ClassNotFoundException|SQLException e) {
            e.printStackTrace();
        }
    }
    

    public static void main(String[] args) {
    initialInsert(); // writes a new name but does not commit
    readUncommited(); // reads the "name" parameter in a table
    
    }


    public static void initialInsert() {


        String SQL = "INSERT INTO Person VALUES(?,?,?)";
        try {
            PreparedStatement preparedStatement = connection.prepareStatement(SQL);
            preparedStatement.setInt(1,1);

            preparedStatement.setString(2,"Mike");
            preparedStatement.setInt(3,32);
            preparedStatement.executeUpdate();

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    public static void readUncommited() {
        String SQL2Read = "SELECT * FROM Person";
        PreparedStatement preparedStatement = null;
        try {
            preparedStatement = connection.prepareStatement(SQL2Read);
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) System.out.println(resultSet.getString("name"));

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

}

【问题讨论】:

  • 因为一切都发生在同一个连接/事务中
  • @a_horse_with_no_name,谢谢!我必须再问你一个愚蠢的问题。我应该如何使它工作。这样其他方法就无法访问未提交的更改。
  • 等一下...我想每当您在事务之外执行操作时,所有更改/提交都是永久性的,除非它们失败...如果您有多个提交必须全部有效才能最终提交,并且如果任何一个失败,所有更改都将回退/不是永久的。所以我认为这里的问题是将您的操作明确包装到事务中以获得所需的行为......?而且我没有看到分配的交易,所以代码可以正常工作...... IMO
  • 您可能必须实现自己的系统来标记数据是否“可用”或使用多个连接上下文。就数据库而言,一切都由“您”完成,您希望您的未提交更改始终可见。
  • @JayC667 OP 禁用了自动提交模式,这意味着 JDBC 将在必要时启动事务,您负责提交或回滚。您总是在数据库中的事务中工作,尽管有时事务可能会在后台为您透明地启动和提交(“自动提交模式”)。如果没有事务,数据库将不知道它必须提供什么可见性保证。

标签: java sql jdbc spring-transactions


【解决方案1】:

您可以读取未提交的更改,因为这些更改是在写入它们的同一事务中读取的。事务可以看到自己未提交的更改这一事实是正常的,也是意料之中的。

如果您使用了单独的连接(因此使用了单独的事务),您将无法看到这些更改(除非您使用非事务性数据库,如 MySQL 和 MyISAM 存储引擎而不是 InnoDB)。

【讨论】:

    猜你喜欢
    • 2018-11-17
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 2014-02-13
    • 2018-02-06
    • 2017-02-07
    • 2023-01-08
    • 2015-05-20
    相关资源
    最近更新 更多