为什么 SELECT 语句在 SET IMPLICIT TRANSACTION = OFF 并设置 Auto Commit = false 时创建事务?数据库服务器

问题描述

我在示例程序中执行此操作:

    SELECT @@TRANCOUNT;   //COUNT IS 0
    SELECT * FROM CUBE;   //EXECUTE SELECT STATEMENT
    SELECT @@ TRANSCOUNT; // COUNT IS Now 1

我不明白,为什么 sql Server 会为 SELECT 语句创建一个额外的事务?如果 CREATE / UPDATE / DELETE 语句出现,我们的业务逻辑依赖于调用 COMMIT / ROLLBACK?但在这种情况下,由于事务计数为 1,sql Server 不会释放此连接实例持有的资源。

我们可以做些什么来避免在 SELECT 语句的情况下创建事务?

-- 用于执行此案例的代码块:

 try (Connection connection = createNewConnection()) {
            connection.prepareStatement("SET IMPLICIT_TRANSACTIONS OFF").execute();
            connection.setAutoCommit(false);

            System.out.println("Transaction Count [BEFORE] " + transactionCount(connection));

            PreparedStatement preparedStatement = connection.prepareStatement("SELECT COUNT(*) FROM CONNECTIONMetaDATA");
            ResultSet resultSet = preparedStatement.executeQuery();
            if (resultSet.next())
                System.out.println("Connection Count : " + resultSet.getInt(1));

            System.out.println("Transaction Count [AFTER] " + transactionCount(connection));
        } catch (Exception e) {
            e.printstacktrace();
        }


public static int transactionCount(Connection connection) throws sqlException {
        ResultSet resultSet = connection.prepareStatement("SELECT @@TRANCOUNT;").executeQuery();
        return resultSet.next() ? resultSet.getInt(1) : 0;
    }

private static Connection createNewConnection() throws sqlException,ClassNotFoundException {
        String driver = "com.microsoft.sqlserver.jdbc.sqlServerDriver";
        Class.forName(driver);
        String url = "jdbc:sqlserver://DT01070611:1433;databaseName=BI711QA9;";

        Properties props = new Properties();
        props.put("username","BI711QA9");
        props.put("user","BI711QA9");
        props.put("password","BI711QA9");

        return DriverManager.getConnection(url,props);
    }

输出

Transaction Count [BEFORE] 0
Connection Count : 2
Transaction Count [AFTER] 1

上次更新:似乎 setAutoCommit(false) 正在将 SET IMPLICIT_TRANSCATION 触发为 ON。

添加以下块以获取 IMPLICIT TRANSACTION 的当前值

private static String getImplicitTransactionValue(Connection connection) throws sqlException {
        try(PreparedStatement preparedStatement = connection.prepareStatement("DECLARE @IMPLICIT_TRANSACTIONS VARCHAR(3) = 'OFF';" +
                "IF ( (2 & @@OPTIONS) = 2 ) SET @IMPLICIT_TRANSACTIONS = 'ON'; " +
                "SELECT @IMPLICIT_TRANSACTIONS AS IMPLICIT_TRANSACTIONS;");){
            ResultSet resultSet = preparedStatement.executeQuery();
            if(resultSet.next())
                return resultSet.getString(1);
        }
        return "";
    }

修改代码显示每一步后的结果(此处不粘贴该代码) 和输出是:

AT the start: Implicit Transaction Value: OFF
After setting off explicitly: Implicit Transaction Value: OFF
After Auto Commit: Implicit Transaction Value: ON
Transaction Count [BEFORE] 0
Connection Count : 2
Transaction Count [AFTER] 1
Implicit Transaction Value: ON

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)