setAutoCommit(false) sybase SET CHAINED command...异常
2012-11-22 23:24
489 查看
sybase SET CHAINED command...异常
http://zhaixf2001.iteye.com/blog/294610在 Sybase ASE 实际应用中,特别是在 ASE + J2EE 应用中,较容易出现 SET CHAINED command not allowed within multi-statement transaction.的异常(尽管到版本 15.0.1 为止,ASE 并不支持异常机制,但本文为了方便,统一采用“异常”一词)。有的开发人员认为这是 Sybase 数据库的问题;有的认为是多次调用 setAutoCommit() 方法的问题;有的开发人员则认为这是 jConnect 的问题,甚至从 jConnect
的代码上直接屏蔽此异常。
然而,SET CHAINED 异常倒底是怎样产生的?
一、数据库层
首先,让我们看看 set chained。下面的文字片段摘自《ASE 12.5.2 Reference Manual: Commands》,Page 430:
chained
begins a transaction just before the first data retrieval or data modification
statement at the beginning of a session and after a transaction ends. In
chained mode, Adaptive Server implicitly executes a begin transaction
command before the following statements: delete, fetch, insert, lock table,
open, select, and update. You cannot execute set chained within a transaction.
从此段文字可以得知,当 set chained on 后,delete、fetch、insert、lock table、open、select 以及 update 语句将自动启动一个事务,并要求显式的完成事务,即明确地调用 commit/rollback。同时,在事务中,不允许设置 chained 模式。
下面的 sql 代码片断将说明在数据库层上 SET CHAINED 错误信息是如何产生的。
1> set chained on
2> go
1> set chained on
2> go
1> begin tran
2> go
1>
似乎多次调用 set chained 并不会产生异常。接下来,
1> set chained on
2> go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1> set chained off
2> go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1>
显然,处于事务环境下,调用 set chained 是会发生异常的,这一点手册上也非常明确的指出了。但为什么前面的片断中两次连续调用 set chained 却不会产生异常呢?请注意文档上这一句:Adaptive Server implicitly executes a begin transaction command before the following statements: 。
重建一个数据库连接,从头开始:
1> set chained on
2> go
1> select 1
2> go
-----------
1
(1 row affected)
1> set chained on
2> go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1> set chained off
2> go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1>
在执行 select 1 之前,数据库自动启动了一笔事务,因此不能再执行 set chained。接下来,完成隐式启动的事务:
1> rollback
2> go
1> set chained off
2> go
1>
二、J2EE 层
J2EE 应用中,一些轻量级的数据访问层实现采用 Connection 的setAutoCommit(false) + commit()/rollback() 的方式来管理事务。通过对 jConnect 的反编译以及对 spt_mda 数据的分析,可以得知 setAutoCommit(true) = SET CHAINED OFF;setAutoCommit(false) = SET CHAINED ON,下图以顺序图展示调用 setAutoCommit() 方法时,实际发生的交互。
另一方面,J2EE 应用中大多采用了连接池。应用在调用 Connection.close() 方法时,实际上并没有真正地关闭连接,而是将连接回收到池中。假设连接的初态是 chained off。如果应用在取得连接后调用该连接的 setAutoCommit(false) 方法来启动事务,在事务完成后,通过 close() 方法回到池中时,未能恢复到初始状态(即 chained off),则应用多次获取该连接并进行一定操作后,就很有可能出现异常。见下图:
通过上面的分析,理解了产生此异常的原因,就很容易避免此异常,即在完成事务后,关闭连接前,显式地调用 setAutoCommit(true)。或许有的程序员会认为麻烦,但别忘记“完壁归赵”是资源借用者的义务。
---------------------------
autoCommit为false,导致Sybase无法释放链接
博客分类: IT技术
sybaseautoCommit连接未释放
环境:
数据库:sybase 15
连接池:c3p0
问题:
获取Connection之后,设置autoCommit为false;
发现使用后连接池没有释放链接。
开始以为是连接池的bug,后来发现在log中,连接池已经释放链接的方法,
但是没有释放成功。
分析:
相同的代码,换成其他的数据库都没有问题,时候后连接都能被释放。
初步判断是数据库的问题。
解决方案:
求助完成的谷歌大神,找到解决方案
使用完Connection后,需要把autoCommit重新设定为true。
具体是什么原因,目前还不清楚
相关文章推荐
- 事务回滚setAutoCommit(false)
- setAutoCommit(false)导致读不到数据
- conn.setAutoCommit(true)和(false)的区别
- conn.setAutoCommit(false);
- Spring JdbcTemplate的batchUpdate中,没有看到conn.setAutoCommit(false)的操作
- 【数据库】使用Collection.setAutoCommit(false)的注意事项
- conn.setAutoCommit(true)和(false)的区别
- conn.setAutoCommit(false);设置事物手动提交
- conn.setAutoCommit(true)和(false)的区别
- conn.setAutoCommit(true)和(false)的区别
- 中间件不支持setautocommit(false)怎么办?
- 由于没有正确使用Connection.setAutoCommit(false)而导致SQL语句没有被提交
- JDBC conn.setAutoCommit(false) 问题
- setAutoCommit(false); 后没有手动commit. 对数据库有什么影响?
- [Java] JDBC 06 批Transaction处理 -- conn.setAutoCommit(false); // 不让其自动提交 (很重要的知识点)
- conn.setAutoCommit(false)数据回滚设置
- [Java] JDBC 06 批Transaction处理 -- conn.setAutoCommit(false); // 不让其自动提交 (很重要的知识点)
- conn.setAutoCommit(false)
- conn.setAutoCommit()用法及作用(转发)
- Connection.setAutoCommit使用的注意事项