posts - 56, comments - 54, trackbacks - 0, articles - 4
             ::  ::  :: 聯系 :: 聚合  :: 管理

          提交一個查詢有必要用事務嗎?(轉載)

          Posted on 2005-12-06 22:25 Terry的Blog 閱讀(5129) 評論(0)  編輯  收藏 所屬分類: oracle轉載

          如果只提交一個查詢,有必要用事務嗎?這個問題之前已經討論過

          http://forum.javaeye.com/viewtopic.php?t=1603

          但是并沒有得出明確的結論。先讓我們看看事務的定義:

          引用:

          Transactions are described in terms of ACID properties, which are as follows:
          n Atomic: all changes to the database made in a transaction are rolled back if any
          change fails.
          n Consistent: the effects of a transaction take the database from one consistent
          state to another consistent state.
          n Isolated: the intermediate steps in a transaction are not visible to other users of
          the database.
          n Durable: when a transaction is completed (committed or rolled back), its effects
          persist in the database.
           


          即ACID的定義,從上面看來,似乎除了isolated之外,和只讀查詢都沒有關系。那么是否只讀查詢不需要事務呢?

          再看看Oracle對于只讀事務的定義:

          引用:
          Read-Only Transactions
          By default, Oracle guarantees statement-level read consistency. The set of data returned by a single query is consistent with respect to a single point in time. However, in some situations, you might also require transaction-level read consistency. This is the ability to run multiple queries within a single transaction, all of which are read-consistent with respect to the same point in time, so that queries in this transaction do not see the effects of intervening committed transactions.

          If you want to run a number of queries against multiple tables and if you are not doing any updating, you prefer a read-only transaction. After indicating that your transaction is read-only, you can run as many queries as you like against any table, knowing that the results of each query are consistent with respect to the same point in time.


          Oracle默認情況下保證了SQL語句級別的讀一致性,即在該條SQL語句執行期間,它只會看到執行前點的數據狀態,而不會看到執行期間數據被其他SQL改變的狀態。

          而Oracle的只讀查詢(read-only transaction)則保證了事務級別的讀一致性,即在該事務范圍內執行的多條SQL都只會看到執行前點的數據狀態,而不會看到事務期間的任何被其他SQL改變的狀態。

          因此我們可以得出結論:

          如果你一次執行單條查詢語句,則沒有必要啟用事務支持,數據庫默認支持SQL執行期間的讀一致性;
          如果你一次執行多條查詢語句,例如統計查詢,報表查詢,在這種場景下,多條查詢SQL必須保證整體的讀一致性,否則,在前條SQL查詢之后,后條SQL查詢之前,數據被其他用戶改變,則該次整體的統計查詢將會出現讀數據不一致的狀態,此時,應該啟用事務支持。


          只讀事務與讀寫事務區別

          對于只讀查詢,可以指定事務類型為readonly,即只讀事務。由于只讀事務不存在數據的修改,因此數據庫將會為只讀事務提供一些優化手段,例如Oracle對于只讀事務,不啟動回滾段,不記錄回滾log。

          在JDBC中,指定只讀事務的辦法為:
          connection.setReadOnly(true);

          在Hibernate中,指定只讀事務的辦法為:
          session.setFlushMode(FlushMode.NEVER);
          此時,Hibernate也會為只讀事務提供Session方面的一些優化手段

          在Spring的Hibernate封裝中,指定只讀事務的辦法為:
          bean配置文件中,prop屬性增加“readOnly”

           

          我在MySQL4.1試驗了一下,過程和結果如下:

          數據庫:MySQL4.1
          表類型:InnoDB
          Spring:1.1.2
          Hibernate:2.1.7

          使用Spring的聲明式事務管理

          試驗過程如下:

          不設置查詢方法的事務類型(即不需要事務):訪問查詢頁面,后臺執行Spring的Bean方法,讓Hibernate發送select語句,然后手工在MySQL里面修改該記錄某字段值,再訪問查詢頁面,發現被修改過的字段值并沒有變化,Hibernate輸出的log顯示,數據庫還是把老的字段值返回,而沒有返回新的字段值。

          設置查詢方法的事務類型(只讀事務):訪問查詢頁面,后臺執行Spring的Bean方法,讓Hibernate發送select語句,然后手工在MySQL里面修改該記錄某字段值,再訪問查詢頁面,發現被修改過的字段值已經變化,Hibernate輸出的log顯示,數據庫返回新的字段值。

          這個試驗說明,至少在MySQL4.1的InnoDB情況下,不使用只讀事務的查詢將無法讀取到數據更新值,必須使用只讀事務來保證讀記錄的數據一致性。這個結果非常令我詫異,和我預期完全兩樣。

          我將在Oracle平臺上試試看會有什么樣的結果。

          BTW: 如果MySQL的表類型改為MyISAM,那么即使不設置事務,也不會出現讀數據不一致的現象。


          oracle有兩種方法保證在事務級讀數據一致性(Transaction-Level Read Consistency)

          一是用SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ,
          當執行這條命令后讀數據時會產生一些重復copy, 你也可以做數據修改, 但在大量數據修改的情況下容易造成deadlock或異常, 用commit或rollback將把ISOLATION LEVEL設回為缺省模式read committed,


          二是用SET TRANSCATION READ ONLY
          當執行這條命令時數據庫會生成一個快照的latch, 這個latch會耗費一些resource, 如果你想進行數據修改會導致異常. 用commit或rollback會把latch釋放掉, 也將把ISOLATION LEVEL設回為缺省模式read committed,

          主站蜘蛛池模板: 平顺县| 浏阳市| 水富县| 泰州市| 奉化市| 巴彦淖尔市| 黔西| 黄冈市| 外汇| 牡丹江市| 鹤山市| 淳化县| 晋宁县| 涿鹿县| 乌兰察布市| 新余市| 衡阳县| 辉县市| 奉新县| 固阳县| 崇礼县| 延川县| 韶关市| 辰溪县| 祁门县| 育儿| 巫溪县| 绥棱县| 深州市| 清远市| 长治县| 从江县| 通化市| 瓮安县| 平谷区| 庆元县| 来宾市| 紫阳县| 青冈县| 乌兰察布市| 广汉市|