惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Blog — PlanetScale
Blog — PlanetScale
SecWiki News
SecWiki News
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
小众软件
小众软件
C
CERT Recently Published Vulnerability Notes
Jina AI
Jina AI
N
Netflix TechBlog - Medium
GbyAI
GbyAI
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
AWS News Blog
AWS News Blog
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
C
Cybersecurity and Infrastructure Security Agency CISA
I
Intezer
T
Tor Project blog
P
Palo Alto Networks Blog
P
Privacy & Cybersecurity Law Blog
P
Privacy International News Feed
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Proofpoint News Feed
T
Tailwind CSS Blog
C
Check Point Blog
Cloudbric
Cloudbric
Y
Y Combinator Blog
The Last Watchdog
The Last Watchdog
Forbes - Security
Forbes - Security
Last Week in AI
Last Week in AI
S
Security Affairs
博客园 - Franky
F
Fortinet All Blogs
量子位
M
MIT News - Artificial intelligence
C
Cisco Blogs
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
S
Secure Thoughts
V
Visual Studio Blog
AI
AI
美团技术团队
B
Blog RSS Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 三生石上(FineUI控件)
阮一峰的网络日志
阮一峰的网络日志
Engineering at Meta
Engineering at Meta
人人都是产品经理
人人都是产品经理
Microsoft Security Blog
Microsoft Security Blog
T
Threatpost
Cyberwarzone
Cyberwarzone

博客园 - 马森

Java IO测试样例-字节流-字符流 java中的io系统详解 MongoDB资料汇总 字符编码笔记:ASCII,Unicode和UTF-8 jQuery和ExtJS的timeOut超时设置和event事件处理 Sybase字符串函数-数学函数-系统函数 inux 设置系统时间和硬件时间 Sybase采用固定表+存储过程实现分页 Wordpress XML-RPC协议说明 struts2 action 配置方法 &&struts2的配置文件 sybase性能优化 - 马森 - 博客园 Java引用对象SoftReference WeakReference PhantomReference(二) [整理]centos下配置和安装 jstl字符串处理 [原]动态打jar包程序,可用于手机图片音乐游戏的动态打包 Java,Tomcat,Mysql乱码总结 [原]output parameters have not yet been processed源自返回了多个数据集 [转]MS SQL Server数据库事务锁机制分析 tomcat支持ssl时Keystore was tampered with, or password was incorrect
理解 SET CHAINED command not allowed within multi-statement transaction.
马森 · 2011-03-18 · via 博客园 - 马森

在 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)。或许有的程序员会认为麻烦,但别忘记“完壁归赵”是资源借用者的义务。

[ 转]

posted on 2011-03-18 11:32  马森  阅读(910)  评论()    收藏  举报