首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JTDS和交易

JTDS和交易
EN

Stack Overflow用户
提问于 2014-11-06 20:17:45
回答 1查看 1.9K关注 0票数 3

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

首先,请看这两个程序。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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调用他们,下面的代码

代码语言:javascript
复制
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

这是我所期望的结果。

代码语言:javascript
复制
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执行相同的过程时,正如下面的代码所示,我看到了奇怪的行为。

代码语言:javascript
复制
    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();

我看到了以下输出:

代码语言:javascript
复制
- Guarded StartTC: 0, TC: 2
- Unguarded StartTC: 0, TC: 2

由于我希望看到与上面的“包装”示例相同的值(正如我理解JDBC在调用setAutoCommit(false)时开始一个新事务一样),我真的不知道发生了什么。有洞察力吗?

更多信息:

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

代码语言:javascript
复制
MSFT Driver - Guarded StartTC: 1, TC: 1
MSFT Driver - Unguarded StartTC: 1, TC: 2
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-11-10 22:24:18

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

我假设在调用了jTDS之后,setAutoCommit(false)显式地开始了连接的事务。事实上,它的行为并不是这样的。它所做的就是在连接上发出一个SET IMPLICIT_TRANSACTIONS ON

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

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

代码语言:javascript
复制
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

我们得到以下信息:

代码语言:javascript
复制
Description        StartTranCount TranCount
------------------ -------------- -----------
UNGUARDED_IMPLICIT 0              2

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

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26788640

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档