gpt4 book ai didi

sql-server - JTDS 和事务

转载 作者:行者123 更新时间:2023-12-02 01:44:01 25 4
gpt4 key购买 nike

当我直接从 SSMS 调用存储过程 (MSSQL 2008R2) 或从 JTDS 调用它时,我看到了不同的行为。

首先,请看这两个程序。

CREATE PROCEDURE [Template].[UnguardedTest]
@outparam_StartTransactionCount INT OUTPUT,
@outparam_TransactionCount INT OUTPUT

AS

BEGIN

SET NOCOUNT ON;
SET XACT_ABORT ON;

DECLARE @StartTranCount INT

SELECT @StartTranCount = @@TRANCOUNT

BEGIN TRANSACTION

BEGIN
SELECT @outparam_StartTransactionCount = @StartTranCount
SELECT @outparam_TransactionCount = @@TRANCOUNT
END

COMMIT TRANSACTION

END

第二个与第一个非常相似,除了它不会开始(也不会提交)事务,除非入口处的 @@TRANCOUNT 为 0。

CREATE PROCEDURE [Template].[GuardedTest]
@outparam_StartTransactionCount INT OUTPUT,
@outparam_TransactionCount INT OUTPUT

AS

BEGIN

SET NOCOUNT ON;
SET XACT_ABORT ON;

DECLARE @StartTranCount INT

-- Record the @@TRANCOUNT at the beginning of this procedure / trigger.
SELECT @StartTranCount = @@TRANCOUNT

IF @StartTranCount = 0
BEGIN TRANSACTION

BEGIN
SELECT @outparam_StartTransactionCount = @StartTranCount
SELECT @outparam_TransactionCount = @@TRANCOUNT
END

IF @StartTranCount = 0
COMMIT TRANSACTION

END

如果我使用下面的代码从 SSMS 调用它们

DECLARE @outparam_TransactionCount INT
DECLARE @outparam_StartTransactionCount INT

EXECUTE [Template].[UnguardedTest] @outparam_StartTransactionCount OUTPUT, @outparam_TransactionCount OUTPUT
SELECT 'UNGUARDED_NOT_WRAPPED' AS Description, @outparam_StartTransactionCount AS [StartTranCount], @outparam_TransactionCount AS [TranCount]

BEGIN TRAN
EXECUTE [Template].[UnguardedTest] @outparam_StartTransactionCount OUTPUT, @outparam_TransactionCount OUTPUT
SELECT 'UNGUARDED_WRAPPED' AS Description, @outparam_StartTransactionCount AS [StartTranCount], @outparam_TransactionCount AS [TranCount]
COMMIT TRAN

EXECUTE [Template].[GuardedTest] @outparam_StartTransactionCount OUTPUT, @outparam_TransactionCount OUTPUT
SELECT 'GUARDED_NOT_WRAPPED' AS Description, @outparam_StartTransactionCount AS [StartTranCount], @outparam_TransactionCount AS [TranCount]

BEGIN TRAN
EXECUTE [Template].[GuardedTest] @outparam_StartTransactionCount OUTPUT, @outparam_TransactionCount OUTPUT
SELECT 'GUARDED_WRAPPED' AS Description, @outparam_StartTransactionCount AS [StartTranCount], @outparam_TransactionCount AS [TranCount]
COMMIT TRAN

输出是我所期望的。

Description           StartTranCount TranCount
--------------------- -------------- -----------
UNGUARDED_NOT_WRAPPED 0 1

Description StartTranCount TranCount
----------------- -------------- -----------
UNGUARDED_WRAPPED 1 2

Description StartTranCount TranCount
------------------- -------------- -----------
GUARDED_NOT_WRAPPED 0 1

Description StartTranCount TranCount
--------------- -------------- -----------
GUARDED_WRAPPED 1 1

在事务中包装对过程的调用会导致 StartTranCount 为 1,否则为零。

但是,当我按照下面的代码通过 JTDS/JDBC 执行相同的过程时,我看到了奇怪的行为。

    int tc = -1, startTC = -1;

final Connection con2 = DriverManager.getConnection(url);
con2.setAutoCommit(false);
final CallableStatement proc2 = con2.prepareCall("{ call Template.GuardedTest(?,?) }");
proc2.registerOutParameter("@outparam_StartTransactionCount", Types.INTEGER);
proc2.registerOutParameter("@outparam_TransactionCount", Types.INTEGER);
proc2.execute();
startTC = proc2.getInt("@outparam_StartTransactionCount");
tc = proc2.getInt("@outparam_TransactionCount");
log.info("Guarded StartTC: " + startTC + ", TC: " + tc);
proc2.close();
con2.commit();
con2.close();

final Connection con1 = DriverManager.getConnection(url);
con1.setAutoCommit(false);
final CallableStatement proc1 = con1.prepareCall("{ call Template.UnguardedTest(?,?) }");
proc1.registerOutParameter("@outparam_StartTransactionCount", Types.INTEGER);
proc1.registerOutParameter("@outparam_TransactionCount", Types.INTEGER);
proc1.execute();
startTC = proc1.getInt("@outparam_StartTransactionCount");
tc = proc1.getInt("@outparam_TransactionCount");
log.info("Unguarded StartTC: " + startTC + ", TC: " + tc);
proc1.close();
con1.commit();
con1.close();

我看到了以下输出:

- Guarded StartTC: 0, TC: 2
- Unguarded StartTC: 0, TC: 2

因为我期望看到与上面的“包装”示例相同的值(据我所知,JDBC 在调用 setAutoCommit(false) 时开始一个新事务,我真的很茫然至于发生了什么。有什么见解吗?

附加信息:

如果我切换到 Microsoft JDBC 驱动程序,我会得到预期的结果

MSFT Driver - Guarded StartTC: 1, TC: 1
MSFT Driver - Unguarded StartTC: 1, TC: 2

最佳答案

我发现了这种行为的原因。

我假设 jTDS 在 setAutoCommit(false) 被调用后明确地开始连接事务。事实上,它的行为并非如此。它所做的是在连接上发出 SET IMPLICIT_TRANSACTIONS ON

根据 Microsoft (http://msdn.microsoft.com/en-us/library/ms187807.aspx) - “当 IMPLICIT_TRANSACTIONS = ON 时,显式 BEGIN TRANSACTION 将启动两个嵌套事务。”

例如,如果我们在 SSMS 中执行以下操作

SET IMPLICIT_TRANSACTIONS ON
EXECUTE [Template].[UnguardedTest] @outparam_StartTransactionCount OUTPUT, @outparam_TransactionCount OUTPUT
SELECT 'UNGUARDED_IMPLICIT' AS Description, @outparam_StartTransactionCount AS [StartTranCount], @outparam_TransactionCount AS [TranCount]
COMMIT TRAN

SET IMPLICIT_TRANSACTIONS ON
EXECUTE [Template].[GuardedTest] @outparam_StartTransactionCount OUTPUT, @outparam_TransactionCount OUTPUT
SELECT 'GUARDED_IMPLICIT' AS Description, @outparam_StartTransactionCount AS [StartTranCount], @outparam_TransactionCount AS [TranCount]
COMMIT TRAN

我们得到以下信息:

Description        StartTranCount TranCount
------------------ -------------- -----------
UNGUARDED_IMPLICIT 0 2

Description StartTranCount TranCount
---------------- -------------- -----------
GUARDED_IMPLICIT 0 2

这与我们在 jTDS 执行这些过程时得到的输出一致。

关于sql-server - JTDS 和事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26788640/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com