通过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 packagecom.bea.cs.test.jdbc;

3 importcom.bea.cs.test.utils.JNDIRetriver;
4 importjava.sql.*;
5 importjava.io.*;
6 importjavax.transaction.*;

8 publicclassSQLServerJDBCTest {

10 publicstaticvoidmain(String args[])
11 {
12 SQLServerJDBCTest test =newSQLServerJDBCTest();
13 
14 for(intloop=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(intloop=0; loop<15; loop++)
22 test.checkAutoCommit("jdbc/SQLServerNonXADS");
23 }
24 
25 publicvoidcheckAutoCommit(String dsName)
26 {
27 CheckAutoCommitThread cacThread =newCheckAutoCommitThread(dsName);
28 cacThread.start();
29 }
30 
31 classCheckAutoCommitThread extendsThread
32 {
33 privateString dsName =null;
34 
35 publicCheckAutoCommitThread(String ds){
36 dsName =ds;
37 }
38 
39 privatevoidcallProc(String dsName, intloop)
40 {
41 ProcThread procThread =newProcThread(dsName, loop);
42 procThread.start();
43 }
44 
45 classProcThread extendsThread
46 {
47 privateString ds =null;
48 privateintid =-1;
49 
50 publicProcThread(String dsName, intloop)
51 {
52 ds =dsName;
53 id =loop;
54 }
55 
56 publicvoidrun()
57 {
58 String url ="t3://10.130.2.90:7001";
59 String sql ="{ call TestProc() }";
60 Connection conn =null;
61 JNDIRetriver retriever =newJNDIRetriver(url);
62 try{
63 conn =retriever.getJBDCConnection(ds);
64 booleanautoCommit =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 =newConnCloseThread(conn, id);
72 closeThread.start();
73 longstart =System.currentTimeMillis();
74 System.out.println( "execute-"+id +"starts at: "+start/1000.0);
75 cstmt.execute();
76 longend =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 classConnCloseThread extendsThread
91 {
92 privateConnection connection =null;
93 privateintid =-1;
94 
95 publicConnCloseThread(Connection conn, intloop){
96 connection =conn;
97 id =loop;
98 }
99 
100 publicvoidrun()
101 {
102 try{
103 Thread.currentThread().sleep(10000);
104 //connection.rollback();
105 longstart =System.currentTimeMillis();
106 System.out.println( "closeConn-"+id +"starts at: "+start/1000.0);
107 connection.close();
108 longend =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亦如此,毕竟事务嵌套了以后,管理起来是个问题,完整性更是个问题。

本文出自:冯立彬的博客

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

服务器无法继续该事务 3400000006 错误原因--JAVA调用SQLSERVER存储过程时过程发生异常内部事务未相关推荐

  1. 关于调用Oracle存储过程时发生“BCD Overflow”错误的处理

    笔者最近在使用TSQLStoredProc调用Oracle存储过程时发现,即使存储过程体为空时,都会发生 BCD Overflow 错误,该表部分定义如下: PLANE_ALL_PARAMETER表: ...

  2. windows服务安装错误 在‘安装’过程发生异常:System.ComponentModel.Win32Exception:系统正在关机

    windows服务安装错误 在'安装'过程发生异常:System.ComponentModel.Win32Exception:系统正在关机 参考文章: (1)windows服务安装错误 在'安装'过程 ...

  3. Apache服务器 403 Forbidden的几种错误原因小结!

    403 Forbidden错误原因详解 403 - Forbidden(禁止访问),服务器拒绝请求 - forbidden request (matches a deny filter) => ...

  4. android获取错误原因,从http读取数据时发生OutOfMemory错误获取请求android

    我正在做一个http获取请求.我需要接收大量数据,但在读取数据时出现OutOfMemory异常.从http读取数据时发生OutOfMemory错误获取请求android 我的代码: public st ...

  5. php保存成乱序,php – 调用MySQL存储过程时出现乱序错误

    我正在尝试使用PDO调用存储过程,但在尝试对结果进行获取时遇到以下错误. 警告:数据包乱序.预计1收到16.数据包大小= 163 我的存储过程使用两个游标,我在从临时表中选择之前关闭它.我怀疑这可能是 ...

  6. 【java基础】子线程任务发生异常,主线程事务如何回滚?

    文章目录 一.提出问题 二.主线程与子线程 三.线程池 四.异常的捕获 五.事务的回滚 一.提出问题 最近有一位朋友问了我这样一个问题,问题的截图如下: 这个问题问的相对比较笼统,我来稍微详细的描述下 ...

  7. PHP写sqlserver事务,php调用sqlserver存储过程使用事务处理

    第一次编写 sqlserver存储过程并在php里调用,把脑瓜都整大了,奋战了一天多最后还是搞定了. 实现功能:在 sqlserver里面实现事务处理,保证数据库操作安全: 接收sqlserver存储 ...

  8. Java调用oracle存储过程报无效的列索引的错误

    今天第一次在java中调用数据库的存储过程,直接上代码 public void insertSql(String taskCode, String exeSql)throws Exception{ja ...

  9. Spring高级之Spring事务详解(用法、传播行为、隔离级别、只读事务、事务条件)

    前言 这是之前开始学spring的时候的笔记,现在添加了一些理解,然后把他搬到博客上来. 事务概述: 这里仅对数据库事务进行一个概述,要详细的可以查询相关文章 在JavaEE企业级开发的应用领域,为确 ...

最新文章

  1. PDF转换图片,图片的切割,图片转换PDF以及PDF加水印等记录贴
  2. 喜欢←划,不喜欢→划
  3. mysql必知必会学习笔记(一)
  4. matlab png转02,matlab把图片pgm格式转换成png格式
  5. 《看聊天记录都学不会C#?太菜了吧》(3)变量:我大哥呢?$:小弟我罩着你!
  6. angular-cli构建
  7. js页面自适应屏幕大小_移动端自适应布局方法的calc()与vw
  8. sql:无法解决 equal to 操作中 Chinese_PRC_CI_AS 和 Chinese_Taiwan_Stroke_CI_AS 之间的排序规则冲突。...
  9. c++ 查找文件夹下最新创建的文件_云计算开发总结:搜索Linux文件和文件夹的方法...
  10. 通过浏览器启动php cli,Cron作业PHP脚本失败但脚本将通过CLI或浏览器运行
  11. 【洛谷 P4291】 [HAOI2008]排名系统(Splay,Trie)
  12. 大数据时代:如何节省存储成本
  13. ffmpeg 推流同时录像命令_使用FFmpeg将rtsp流摄像头视频转码为rtmp播放
  14. 【5G系列】Network Slicing学习总结(4)
  15. 提升小程序UV访客,快速开通流量主
  16. 用一个例子说明什么是多态
  17. linux timerfd系列函数学习笔记2 获取超时次数
  18. 《图像处理实例》 之 疏密程度统计
  19. mysql主从复制,互为主从与读写分离
  20. flash Builder eclipse 恢复英文

热门文章

  1. CoralCache:一个提高微服务可用性的中间件
  2. 实践案例丨GaussDB网络重传/丢包问题定位总结
  3. 2020HC大会上,这群人在讨论云原生…
  4. 前端常用60余种工具方法(上)
  5. #化鲲为鹏,我有话说# 鲲鹏弹性云服务器配置 Tomcat
  6. Modelarts与无感识别技术生态总结(浅出版)
  7. 充满含金量的一场云原生Meetup,入场券免费发送中……
  8. 消息队列应用场景解析
  9. c++ 设置类型别名
  10. 做柜员还是程序员_应届生放弃互联网大厂回家乡银行:程序员五万比不上柜员五千...