廖铮www.chinai tp 采集 ow er.comKegMw
2002-5-30 14:23:50
然後,再打開另一個SQLPlus實例——更新實例來執行以下命令:
SQL> update hr.employees
2 set salary = salary * 1.05
3 where
4 department_id = 20
5 /
代碼執行後回復消息稱兩行數據已被更新。
注意,以上代碼中並每有像在SQL Server示例那樣鍵入“begin tran”字樣的代碼。Oracle 的SQLPlus隱含啟用交易(你還可以模仿SQL Server的行為,設置“autocommit to on”自動地提交交易)。接下來我們在SQLPlus更新實例中再執行同查詢實例一樣的select語句。
結果清楚地表明:Michael和Pat的薪水都增加了,然而這個時候我還沒有提交數據變更交易。
現在轉到第1個SQLPlus查詢實例重新運行查詢,結果如下:
Oracle不需要用戶等待數據更新實例中操作被提交,它徑直返回Michael和Pat的查詢信息,但實際上返回的是數據更新開始之前的數據視圖!
這時候,熟悉SQL Server的人可能會說了,在查詢中設置(NOLOCK)不也能達到同樣的效果嗎?可是,對SQL Server而言,在數據映像之前是不能獲取數據的。指定(NOLOCK)實際上只是得到了沒有提交的數據。Oracle的方法則提供了數據的一致視圖,所有的信息都是針對交易的、基於存儲數據快照的。
如果在SQLPlus的更新實例中提交更新交易在查詢實例中就能看到薪水數據發生變化。如果在查詢實例中重新運行先前的查詢語句,那麼Oracle將返回新的薪水數值。
存儲數據快照
說了半天,在給用戶顯示先前版本的數據同時,Oracle是如何允許其他用戶修改數據的呢?其實,只要某一用戶啟動了一宗修改數據的交易,之前的數據映像就會被寫到一個特殊的存儲區域。這種“前映像”用來向任何查詢數據的用戶提供一致的數據庫視圖。這樣,當其他用戶在修改數據的時候,在以上的測試中我們就能看到尚未發生變更的薪金數據。
這個特殊的存儲區域在哪裡呢?這個問題的答案就跟你正在使用的Oracle版本有關了。在 Oracle 8i及其以前版本中會為這一目的創建特殊的回滾段。然而,這種舉措會給數據庫管理員(DBA)帶來管理和調整數據段的工作負擔。例如,DBA必須確定為此需要的數據段的數量以及大小等。假如回滾段沒有正確配置,那麼對交易而言它們就可能不得不排隊等待回滾段中出現必要的數據空間。
Oracle 9i就不同了,這是Oracle的最新版本,Oracle實現了一種新特性,這就是所謂的undo表空間,它有效地消除了以上的管理復雜性。雖然回滾段仍然可以繼續使用,但是,DBA現在可以選擇創建undo表空間的方式令Oracle自己管理“前映像”的復雜空間分配。
Oracle的這種方法對程序員具有重要意義。因為回滾空間不是無限的,所以,更新交易的數據快照會取代先前交易的映像。因此,如果必要的回滾段被其他交易的映像覆蓋的話。運行時間較長的查詢操作就可能產生“ snapshot too old”錯誤。
下面舉個可能發生的案例。假設在上午11:59的時候某位職員開始更新John Doe帳務的交易。這宗交易在下午12:01被提交。同時,下午12:00某財務經理開始查詢所有的客戶帳務報表和當月收費總計。因為客戶很多,所以這一查詢操作很費了點時間,但是不論這次操作到底執行了多久,反正它檢索出的結果就是下午12:00數據庫中存在的數據。如果包含John Doe帳務前映像的回滾空間在查詢執行到該客戶名字的時候被覆蓋則查詢返回錯誤消息。
Oracle的解決方案當然更為合理,在抽象意義上提供了相比SQL Server更佳的數據一致性。在執行Oracle查詢的時候無須擔心較長的查詢操作會鎖定重要的交易。但是,在兩種數據庫同時支持海量用戶的情況下也很難證明Oracle是否就能真正實現具體條件下的數據一致性。
關鍵詞: