歲月如哥
          人生非夢(mèng)
          posts - 50,comments - 144,trackbacks - 0
          在 Sybase ASE 實(shí)際應(yīng)用中,特別是在 ASE + J2EE? 應(yīng)用中,較容易出現(xiàn) SET CHAINED command not allowed within multi-statement transaction.的異常(盡管到版本 15.0.1 為止,ASE 并不支持異常機(jī)制,但本文為了方便,統(tǒng)一采用“異常”一詞)。有的開發(fā)人員認(rèn)為這是 Sybase 數(shù)據(jù)庫的問題;有的認(rèn)為是多次調(diào)用 setAutoCommit() 方法的問題;有的開發(fā)人員則認(rèn)為這是 jConnect 的問題,甚至從 jConnect 的代碼上直接屏蔽此異常。
            然而,SET CHAINED 異常倒底是怎樣產(chǎn)生的?
            一、數(shù)據(jù)庫層
            首先,讓我們看看 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.
          
            從此段文字可以得知,當(dāng) set chained on 后,delete、fetch、insert、lock table、open、select 以及 update 語句將自動(dòng)啟動(dòng)一個(gè)事務(wù),并要求顯式的完成事務(wù),即明確地調(diào)用 commit/rollback。同時(shí),在事務(wù)中,不允許設(shè)置 chained 模式。
            下面的 sql 代碼片斷將說明在數(shù)據(jù)庫層上 SET CHAINED 錯(cuò)誤信息是如何產(chǎn)生的。
          1> set chained on
          2> go
          1> set chained on
          2> go
          1> begin tran
          2> go
          1>
          
            似乎多次調(diào)用 set chained 并不會(huì)產(chǎn)生異常。接下來,
          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>
          
            顯然,處于事務(wù)環(huán)境下,調(diào)用 set chained 是會(huì)發(fā)生異常的,這一點(diǎn)手冊(cè)上也非常明確的指出了。但為什么前面的片斷中兩次連續(xù)調(diào)用 set chained 卻不會(huì)產(chǎn)生異常呢?請(qǐng)注意文檔上這一句:Adaptive Server implicitly executes a begin transaction command before the following statements:
            重建一個(gè)數(shù)據(jù)庫連接,從頭開始:
          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>
          
            在執(zhí)行 select 1 之前,數(shù)據(jù)庫自動(dòng)啟動(dòng)了一筆事務(wù),因此不能再執(zhí)行 set chained。接下來,完成隱式啟動(dòng)的事務(wù):
          1> rollback
          2> go
          1> set chained off
          2> go
          1>
          
            二、J2EE 層
            J2EE 應(yīng)用中,一些輕量級(jí)的數(shù)據(jù)訪問層實(shí)現(xiàn)采用 Connection 的setAutoCommit(false) + commit()/rollback() 的方式來管理事務(wù)。通過對(duì) jConnect 的反編譯以及對(duì) spt_mda 數(shù)據(jù)的分析,可以得知 setAutoCommit(true) = SET CHAINED OFF;setAutoCommit(false) = SET CHAINED ON,下圖以順序圖展示調(diào)用 setAutoCommit()  方法時(shí),實(shí)際發(fā)生的交互。

          理解 SET CHAINED command not allowed within multi-statement transaction.


            另一方面,J2EE 應(yīng)用中大多采用了連接池。應(yīng)用在調(diào)用 Connection.close() 方法時(shí),實(shí)際上并沒有真正地關(guān)閉連接,而是將連接回收到池中。假設(shè)連接的初態(tài)是 chained off。如果應(yīng)用在取得連接后調(diào)用該連接的 setAutoCommit(false) 方法來啟動(dòng)事務(wù),在未完成事務(wù)的情況下,通過 close() 方法回到池中,則當(dāng)該連接下一次被取出并調(diào)用 setAutoCommit(false) 方法時(shí)就會(huì)拋出異常。見下圖:

            通過上面的分析,理解了產(chǎn)生此異常的原因,就很容易避免此異常,即調(diào)用了 setAutoCommit(false) 后,必須顯示地完成事務(wù),即使只是執(zhí)行了一個(gè)select語句。同時(shí),關(guān)閉連接前,應(yīng)顯式地調(diào)用 setAutoCommit(true)。或許有的程序員會(huì)認(rèn)為麻煩,但別忘記“完壁歸趙”是資源借用者的義務(wù)。
          posted on 2009-03-02 17:48 歲月如歌 閱讀(1635) 評(píng)論(1)  編輯  收藏 所屬分類: java

          FeedBack:
          # re: 理解 SET CHAINED command not allowed within multi-statement transaction. (zz)
          2009-03-26 01:29 | jasion
          講述透切,非常感謝!  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 通道| 贵德县| 绍兴市| 修武县| 富宁县| 满城县| 鄂托克前旗| 娄底市| 兴仁县| 宁南县| 九寨沟县| 罗定市| 莱州市| 交口县| 彩票| 达日县| 卢氏县| 岳普湖县| 年辖:市辖区| 南澳县| 丰镇市| 临桂县| 新源县| 招远市| 蒲城县| 乌拉特前旗| 邯郸县| 赤峰市| 北安市| 柳江县| 南郑县| 台湾省| 日喀则市| 凌源市| 禹城市| 石狮市| 高密市| 泰顺县| 张家口市| 德令哈市| 息烽县|