1. 程式人生 > >"伺服器無法繼續該事務 3400000006"錯誤原因--JAVA呼叫SQLSERVER儲存過程時過程發生異常內部事務未提交

"伺服器無法繼續該事務 3400000006"錯誤原因--JAVA呼叫SQLSERVER儲存過程時過程發生異常內部事務未提交

    通過JAVA呼叫SQLSERVER儲存過程時,儲存過程內部發生了型別轉換異常,在型別轉換異常發生之前已經將事務打開了,並且在型別轉換那一行沒有采用像如下錯誤處理:

    if @@error<>0 then

        goto err

    end

    導致了過程在發生異常的時候直接中斷返回JAVA,此時過程內部的事務並沒有提交,根據MICROSOFT的文件如果儲存過程內部有事務並且事務沒有提交,那麼JAVA的事務也不會提交,JAVA的事務須在過程事務提交以後才會被提交。當前系統也採用了連線池,此時JAVA容器直接將沒有提交事務的連線再次放回連線池中,這樣就影響到了後續的交易,如果後續交易使用到了該連線就會報“無法提交事務”的異常,以下是我在部落格園(

http://kb.cnblogs.com/b/237188/)看到的一篇文章,對這樣的錯誤講得非常清楚:

           有個客戶跟我說,他們把weblogic從923升級到923以後,總是提示failed to resume transaction的。當時沒有看到任何資訊,以為跟JTA超時有關,讓客戶把JTA timeout加大,同時把下面的設定加入jdbc-config.xml中。客戶反饋過來說:還是不行。 :( 

    <keep-xa-conn-till-tx-complete>true</keep-xa-conn-till-tx-complete>
    <rollback-local-tx-upon-conn-close>true</rollback-local-tx-upon-conn-close>

        比較鬱悶,後來想想,客戶的jdbc是使用non-XA的driver, 同時將emulate-2pc設為了true,上面連個引數是針對XA的,測試沒有效果應該是正常的。:)  客戶把具體錯誤資訊給我發了過來,如下:

####<2008-10-27 上午10時35分28秒 CST> <Error> <JDBC> <SZSEWEB-YSXAPP> <appServer11> <[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1225074928234> <BEA-001112> <Test "SELECT 1" set up for pool "szseWebDataSource" failed with exception: "java.sql.SQLException: [BEA][SQLServer JDBC Driver][SQLServer]伺服器無法繼續執行該事務。說明: 3c00000047。".> 

        奇怪了,對於non-XA的connection, weblogic做測試的時候,應該是不會其transaction的,而且是直接拿底層的物理connection來做個select,怎麼會有transaction resume呢? 是不是底層物理連接出現了問題? 跟客戶溝通了一下,大概瞭解了他們的應用:通過jdbc呼叫SQL Server的stored procedure,而stored procedure中會起自己的transaction。 Tx中的操作分兩種型別:
1:業務簡單,資料量大
2:資料不大,但業務比較複雜
總之,TX中的SQL執行時間比較長。

        開始懷疑跟客戶的stored procedure有關,建議他先去掉裡面的TX,果然奏效。因為transaction一直是我比較模糊的董東,也不敢跟客戶說:你不能這麼寫,這麼寫是不可以的。畢竟自己底氣不足啊。不是很清楚jdbc connection的auto commit提交的到底是哪個事務,是driver的tx,還是stored procedure裡的tx。應該是前者吧。花了一上午,自己搭了個測試環境,終於復現了這個問題:

儲存過程:

1 create proc dbo.TestProc
2 as
3 begin transaction
4     waitfor delay '00:02:00'5     insert into dbo.TestT_1 values('test')
6 commit


JDBC 程式碼:

  1 package com.bea.cs.test.jdbc;
  2   3 import com.bea.cs.test.utils.JNDIRetriver;
  4 import java.sql.*;
  5 import java.io.*;
  6 import javax.transaction.*;
  7
   8 publicclass SQLServerJDBCTest {
  9  10 publicstaticvoid main(String args[])
 11     {
 12         SQLServerJDBCTest test =new SQLServerJDBCTest();
 13  14 for(int loop=0; loop<15; loop++)
 15             test.callProc("jdbc/SQLServerNonXADS", loop);
 16  17 try{
 18             Thread.currentThread().sleep(10000);
 19         }catch(Exception e){}
 20  21 for(int loop=0; loop<15; loop++)
 22             test.checkAutoCommit("jdbc/SQLServerNonXADS");
 23     }
 24  25 publicvoid checkAutoCommit(String dsName)
 26     {
 27         CheckAutoCommitThread cacThread =new CheckAutoCommitThread(dsName);
 28         cacThread.start();
 29     }
 30  31 class CheckAutoCommitThread extends Thread
 32     {
 33 private String dsName =null;
 34  35 public CheckAutoCommitThread(String ds){
 36             dsName = ds;
 37         }
 38  39 privatevoid callProc(String dsName, int loop)
 40     {
 41         ProcThread procThread =new ProcThread(dsName, loop);
 42         procThread.start();
 43     }
 44  45 class ProcThread extends Thread
 46     {
 47 private String ds =null;
 48 privateint id =-1;
 49  50 public ProcThread(String dsName, int loop)
 51         {
 52             ds = dsName;
 53             id = loop;
 54         }
 55  56 publicvoid run()
 57         {
 58             String url ="t3://10.130.2.90:7001";
 59             String sql ="{ call TestProc() }";
 60             Connection conn =null;
 61             JNDIRetriver retriever =new JNDIRetriver(url);
 62 try{
 63                 conn = retriever.getJBDCConnection(ds);
 64 boolean autoCommit = conn.getAutoCommit();
 65                 CallableStatement cstmt = conn.prepareCall(sql);
 66  67 //start a thread to close current connection, so that a connection
 68 //that attachs a tx will be returned to connection pool and when
 69 //it's retrieved from connection pool by other client, the error
 70 //will be reproduced. 71                 ConnCloseThread closeThread =new ConnCloseThread(conn, id);
 72                 closeThread.start();
 73 long start = System.currentTimeMillis();
 74                 System.out.println( "execute-"+ id +"starts at: "+ start/1000.0);
 75                 cstmt.execute();
 76 long end = System.currentTimeMillis();
 77                 System.out.println("statement "+ id +" execute: "+ (end-start)/1000.0);
 78                 conn.close();
 79             }catch(Exception e)
 80             {
 81 try{
 82                     System.out.println("connection is closed for exception: "+ e.getMessage());
 83                     conn.close();
 84                 }catch(Exception e1){}
 85                 e.printStackTrace();
 86             }
 87         }    
 88     }
 89  90 class ConnCloseThread extends Thread
 91     {
 92 private Connection connection =null;
 93 privateint id =-1;
 94  95 public ConnCloseThread(Connection conn, int loop){
 96             connection = conn;
 97             id = loop;
 98         }
 99 100 publicvoid run()
101         {
102 try{
103                 Thread.currentThread().sleep(10000);
104 //connection.rollback();105 long start = System.currentTimeMillis();
106                 System.out.println( "closeConn-"+ id +"starts at: "+ start/1000.0);
107                 connection.close();
108 long end = System.currentTimeMillis();
109                 System.out.println("close connection "+ id +" takes: "+ (end -start)/1000.0);
110             }catch(Exception e){}
111         }
112     }
113 }
114 115 


        測試結果和預想的有點出入:ConnCloseThread中關閉連線的時候,不是立刻返回的。Connection.close()會觸發Connection.commit(),而因為呼叫的儲存過程中,儲存過程起了自己的事務,connection.commit()必須等到儲存過程結束才能完成(這個是microsoft論壇上看到的)。如果所有connection.close()都等到tx commit或rollback完成才執行的話,這個問題就不會出現了。看看我的測試結果:

statement 5 execute:表示從儲存過程呼叫開始,到呼叫返回的時間
close connection 5 takes:表示關閉連線耗費的時間(也就是connection.commit()等待儲存過程事務結果的時間)

statement 5 execute: 125.922
close connection 5 takes: 148.39
statement 14 execute: 130.031
close connection 14 takes: 148.39
statement 2 execute: 134.031
close connection 2 takes: 148.39
statement 6 execute: 138.14
close connection 6 takes: 148.406
statement 8 execute: 142.14
close connection 8 takes: 148.406
statement 0 execute: 146.156
close connection 0 takes: 148.406
statement 3 execute: 162.39
close connection 3 takes: 168.625
statement 11 execute: 166.39
close connection 11 takes: 168.625

statement 13 execute: 120.0
close connection 13 takes: 115.359
statement 12 execute: 150.265
close connection 12 takes: 148.406
statement 9 execute: 154.281
close connection 9 takes: 148.406
statement 1 execute: 158.39
close connection 1 takes: 148.406
statement 4 execute: 170.5
close connection 4 takes: 168.625
statement 10 execute: 174.515
close connection 10 takes: 168.625
statement 7 execute: 178.609
close connection 7 takes: 168.625

####<Oct 28, 2008 5:59:26 PM CST> <Error> <JDBC> <fjin01> <AdminServer> <[ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1225187966102> <BEA-001112> <Test "SELECT 1" set up for pool "SQLServerNonXADS" failed with exception: "java.sql.SQLException: [BEA][SQLServer JDBC Driver][SQLServer]The server failed to resume the transaction. Desc:3b00000001.".>
####<Oct 28, 2008 5:59:26 PM CST> <Error> <JDBC> <fjin01> <AdminServer> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1225187966132> <BEA-001112> <Test "SELECT 1" set up for pool "SQLServerNonXADS" failed with exception: "java.sql.SQLException: [BEA][SQLServer JDBC Driver][SQLServer]The server failed to resume the transaction. Desc:3e00000001.".>
####<Oct 28, 2008 5:59:26 PM CST> <Error> <JDBC> <fjin01> <AdminServer> <[ACTIVE] ExecuteThread: '31' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1225187966142> <BEA-001112> <Test "SELECT 1" set up for pool "SQLServerNonXADS" failed with exception: "java.sql.SQLException: [BEA][SQLServer JDBC Driver][SQLServer]The server failed to resume the transaction. Desc:3800000001.".>
####<Oct 28, 2008 5:59:26 PM CST> <Error> <JDBC> <fjin01> <AdminServer> <[ACTIVE] ExecuteThread: '4' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1225187966162> <BEA-001112> <Test "SELECT 1" set up for pool "SQLServerNonXADS" failed with exception: "java.sql.SQLException: [BEA][SQLServer JDBC Driver][SQLServer]The server failed to resume the transaction. Desc:3a00000001.".>
####<Oct 28, 2008 5:59:26 PM CST> <Error> <JDBC> <fjin01> <AdminServer> <[ACTIVE] ExecuteThread: '29' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1225187966172> <BEA-001112> <Test "SELECT 1" set up for pool "SQLServerNonXADS" failed with exception: "java.sql.SQLException: [BEA][SQLServer JDBC Driver][SQLServer]The server failed to resume the transaction. Desc:3400000001.".>
####<Oct 28, 2008 5:59:26 PM CST> <Error> <JDBC> <fjin01> <AdminServer> <[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1225187966172> <BEA-001112> <Test "SELECT 1" set up for pool "SQLServerNonXADS" failed with exception: "java.sql.SQLException: [BEA][SQLServer JDBC Driver][SQLServer]The server failed to resume the transaction. Desc:3600000001.".>
####<Oct 28, 2008 5:59:26 PM CST> <Error> <JDBC> <fjin01> <AdminServer> <[ACTIVE] ExecuteThread: '20' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1225187966182> <BEA-001112> <Test "SELECT 1" set up for pool "SQLServerNonXADS" failed with exception: "java.sql.SQLException: [BEA][SQLServer JDBC Driver][SQLServer]The server failed to resume the transaction. Desc:3f00000001.".>


        從測試結果來看,凡是close connection耗時比execute statement短的,連線(物理連線)都會報出該問題。分析原因:通過weblogic datasource獲取的connection並不是物理connection,而是由weblogic wrapped的connection。這些conection在被close後,並不會關閉物理連線,而只是將物理連線還池。我們對connection的所有操作,最終都會被delegated到底層物理連線上,即commit(),rollback()最終都是在物理連線上執行。如果上面的connection.close(),底層物理連線沒有等到儲存過程事務結束就返回的話,那麼物理連線上應該還帶有此次操作的事務,而weblogic這邊不會關係物理連線的情況,直接將連線放入connection pool供其它客戶端使用。這時候如果設定了test on reserve的話,下次客戶端從data source獲取連線時,weblogic會檢查這個物理連線,作一個select操作的,這個有問題的連線就會暴露出來,也就是上面的異常。這個問題如果使用driver manager來獲取連線的話(如果每次都關閉的話),則不會出現,因為使用的物理連線每次都是不同的。還好,weblogic會幫忙重新建立有問題的連線。原因大概瞭解了,但這是誰的問題呢? 為什麼connection.close()不等儲存過程的事務結束?

        結論:一般而言,我們不建議通過JDBC呼叫儲存過程的時候,在儲存過程中定義事務,應該將tx的管理工作交給jdbc去做。 non-xa如此,xa亦如此,畢竟事務嵌套了以後,管理起來是個問題,完整性更是個問題。

相關推薦

"伺服器無法繼續事務 3400000006"錯誤原因--JAVA呼叫SQLSERVER儲存過程過程發生異常內部事務提交

    通過JAVA呼叫SQLSERVER儲存過程時,儲存過程內部發生了型別轉換異常,在型別轉換異常發生之前已經將事務打開了,並且在型別轉換那一行沒有采用像如下錯誤處理:     if @@error<>0 then         goto err     e

伺服器無法繼續執行事務,此會話中的活動事務已由另外一個會話提交或終止。

//執行事務處理 public void DoTran() {  //建立連線並開啟  SqlConnection myConn=GetConn();  myConn.Open();  SqlCommand myComm=new SqlCo

WCF異常資訊:由於內部錯誤伺服器無法處理請求...

    問題錯誤提示:伺服器無法處理請求由於內部錯誤。更多關於這個錯誤的資訊,要麼開啟IncludeExceptionDetailInFaults(從ServiceBehaviorAttribute或從< serviceDebug >配置行為)在伺服器上,以

異常資訊:由於內部錯誤伺服器無法處理請求。有關錯誤的詳細資訊,請開啟伺服器上的 IncludeExceptionDetailInFaults (從 ServiceBehaviorAttribut

不太懂WCF配置檔案,當出現了這種錯誤時,呵呵,就按照上面的提示,作如下操作:在wcf專案下,找到web.config 檔案修改如下(藍色部分) <behaviors>      <serviceBehaviors>        <behavi

無法執行操作,因為連結伺服器 "XXX" 的 OLE DB 訪問介面 "SQLNCLI10" 無法啟動分散式事務

在儲存過程中使用事務,並且使用連結伺服器時,報以下錯誤:   無法執行該操作,因為連結伺服器 "XXX" 的 OLE DB 訪問介面 "SQLNCLI10" 無法啟動分散式事務。 連結伺服器"XXX"的 OLE DB 訪問介面 "SQLNCLI10" 返回了訊息 "沒有活動事務。  

SpringBoot+Shiro引起事務失效、錯誤原因、解決方法

一、問題今天發現使用者註冊的Service的事務並沒有起到作用,再丟擲一個RuntimeException後,並沒有發生回滾,下面是除錯步驟: 1、檢查資料庫的引擎是否是innoDB 2、啟動類上是否加入@EnableTransactionManagement註解 3、是否在方法上加入@Transact

Microsoft SQL Server 2017無法連線到WMI提供程式。您沒有許可權或者伺服器無法訪問...問題的解決方法

本解決方案的原文連結 報錯視窗,解決方案開啟powershell 執行 mofcomp"%programfiles (x86) %\Microsoft SQL Server\號\Shared\sqlmgmproviderxpsp2up.mof" 這行命令 中的“號”指代其中有 “sqlm

計算機意外地重新啟動或遇到錯誤 Windows 安裝無法繼續 若要安裝Windows,請單擊 確定 重新啟動計算機,然後

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

寶塔面板:無法登陸FTP 提示530 錯誤連線不了伺服器 解決

寶塔面板:無法登陸FTP 提示530 錯誤連線不了伺服器 解決 ”無法登陸FTP時,出現530錯誤提示,如下圖 FTP時,出現530錯誤提示 說明你的FTP使用者名稱密碼輸入不正確哦 解決辦法: 1、請在輸入FTP使用者名稱和密碼時,注意不要複製到多餘的空格,否則無法登

exchange shell 報錯winrM 無法處理請求,因為輸入 XML 包含語法錯誤

hang 服務 ntc 卸載 roc vpd 沒有 問題 未能 網卡1和網卡2 互換了一下IP 後連接exchange shell 報錯如下宿主機是HYPER-V平臺互換IP沒有問題,KVM平臺就報錯將IP換過去也沒能解決這個問題卸載exchange重新安裝未能解決最後通過

MySQL 5.7伺服器無法啟動和密碼錯誤

首先,伺服器無法啟動: 第一,在安裝目錄裡建立一個my.ini,內容如下: 1 [mysql] 2 # 設定mysql客戶端預設字符集 3 default-character-set=utf8 4 [mysqld] 5 #設定3306埠 6 por

415錯誤 (Unsupported Media Type 伺服器無法處理請求附帶的媒體格式)

一般是前端傳送資料給後臺,後臺不能識別,造成的。 比如json 字串格式{“key”,“value”} 但是傳送過來的資料value ,有引號的,但是key 一般都不帶的。 所以造成後臺無法解析了。比較快捷的一種解決方式,在SpringMVC配置檔案中加段配置即

ArcMap開始編輯遇到一個或多個有錯誤或警告的圖層,並且無法繼續

開始編輯後可能出現的錯誤: 如果 ArcMap 在所選資料上啟動編輯會話時遇到問題,將彈出一個對話方塊以提供附加資訊。您可能會收到錯誤、警告或資訊訊息。 出現錯誤 時使用者不可以啟動任何編輯會話。只有解決了問題,才能編輯資料。如果沒有可編輯的資料來源、許可授

Spring 事務無法查到新增的資料原因

現象情況 資料庫:MySql 持久化框架:MyBatis Srping 全域性事務配置了兩種: 1. 讀寫事務:使用了 PROPAGATION_REQUIRED 如果當前沒有事務,就新建一個

spring管理事務失效的原因和No mapping found for HTTP request with URI []DispatcherServlet with name 'sprinmvc錯誤

練習了一個spring的事務配置問題,在搭建spring和springmvc時,考驗了一下事務,結果發現事務竟然失效了。這裡做一下總結。 一般我們在Spring的配置檔案application.xml中對Service層程式碼配置事務管理,可以對Service的方法進行AOP增強或事務處理如事務

VC++常見錯誤原因解析之error LNK2019: 無法解析的外部符號 "public: void __thiscall

VC++常見錯誤原因解析之error LNK2019: 無法解析的外部符號 "public: void __thiscall 出現這個錯誤,應該首先檢視“#include”語句是否包含,或者是否包含正確。符號無法解析意味著編譯器知道有這個符號存在,也就是有宣告,但在連結時,找不到實現程式碼,

無法執行操作,因為鏈接服務器 "XXX" 的 OLE DB 訪問接口 "SQLNCLI10" 無法啟動分布式事務

設置 ted -c inf 服務器管理 網絡 右擊 window 存儲過程 在存儲過程中使用事務,並且使用鏈接服務器時,報以下錯誤: 無法執行該操作,因為鏈接服務器 "XXX" 的 OLE DB 訪問接口 "SQLNCLI10" 無法啟動分布式事務。 鏈接服務器"XXX

MFC錯誤0xc000007b 應用程式無法正常啟動 的一種原因

錯誤: 將該程式(32位)拷到一臺64位機子上,提示缺少mfc110u.dll等,於是從開發電腦(64位)上System32裡拷相應的dll到exe的目錄裡,不提示缺dll啦,但出現如下錯誤 原因及對策: win7 64位System32裡的dll為64位的,32位的dl

spring管理事務失效的原因和No mapping found for HTTP request with URI []DispatcherServlet with name 'sprinmvc錯誤

練習了一個spring的事務配置問題,在搭建spring和springmvc時,考驗了一下事務,結果發現事務竟然失效了。這裡做一下總結。 一般我們在Spring的配置檔案application.xml中對Service層程式碼配置事務管理,可以對Service的方法進行AO