2014-11-06 23 views
3

當我直接從SSMS調用存儲過程(MSSQL 2008R2)或從JTDS調用存儲過程時,我會看到不同的行爲。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 

即將事件調用包裝到事務中的過程導致Star​​tTranCount爲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),我真的很茫然,什麼回事任何有識之士

附加信息:?

如果我切換到微軟的JDBC驅動程序,我得到我期望的結果

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

回答

2

我發現了這種行爲的原因。

我認爲在調用setAutoCommit(false)後,jTDS明確開始了連接事務。事實上,它並不是那樣。它所做的是在連接上發出一個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執行這些程序的輸出一致。