Oracle表的優化一點見解


Oracle優化的幾個簡單步驟

數據庫優化的討論可以說是一個永恆的主題。資深的Oracle優化人員通常會要求提出性能問題的人對數據庫做一個statspack,貼出數據庫配置等等。還有的人認為要抓出執行最慢的語句來進行優化。但實際情況是,提出疑問的人很可能根本不懂執行計划,更不要說statspack了。而我認為,數據庫優化,應該首先從大的方面考慮:網絡、服務器硬件配置、操作系統配置、Oracle服務器配置、數據結構組織、然后才是具體的調整。實際上網絡、硬件等往往無法決定更換,應用程序一般也無法修改,因此應該着重從數據庫配置、數據結構上來下手,首先讓數據庫有一個良好的配置,然后再考慮具體優化某些過慢的語句。我在給我的用戶系統進行優化的過程中,總結了一些基本的,簡單易行的辦法來優化數據庫,算是我的三板斧,呵呵。不過請注意,這些不一定普遍使用,甚至有的會有副作用,但是對OLTP系統、基於成本的數據庫往往行之有效,不妨試試。(注:附件是Burleson寫的用來報告數據庫性能等信息的腳本,本文用到)

一.設置合適的SGA
  
  常常有人抱怨服務器硬件很好,但是Oracle就是很慢。很可能是內存分配不合理造成的。
  
  (1)假設內存有512M,這通常是小型應用。建議Oracle的SGA大約240M,其中:共享池(SHARED_POOL_SIZE)可以設置60M到80M,根據實際的用戶數、查詢等來定。數據塊緩沖區可以大致分配120M-150M,8i下需要設置DB_BLOCK_B?RS,DB_BLOCK_B?R*DB_BLOCK_SIZE等於數據塊緩沖區大小。9i 下的數據緩沖區可以用db_cache_size來直接分配。
  
  (2)假設內存有1G,Oracle 的SGA可以考慮分配500M:共享池分配100M到150M,數據緩沖區分配300M到400M。
  
  (3)內存2G,SGA可以考慮分配1.2G,共享池300M到500M,剩下的給數據塊緩沖區。
  
  (4)內存2G以上:共享池300M到500M就足夠啦,再多也沒有太大幫助;(Biti_rainy有專述)數據緩沖區是盡可能的大,但是一定要注意兩個問題:一是要給操作系統和其他應用留夠內存,二是對於32位的操作系統,Oracle的SGA有1.75G的限制。有的32位操作系統上可以突破這個限制,方法還請看Biti的大作吧。
  
  二.分析表和索引,更改優化模式
  
  Oracle默認優化模式是CHOOSE,在這種情況下,如果表沒有經過分析,經常導致查詢使用全表掃描,而不使用索引。這通常導致磁盤I/O太多,而導致查詢很慢。如果沒有使用執行計划穩定性,則應該把表和索引都分析一下,這樣可能直接會使查詢速度大幅提升。分析表命令可以用ANALYZE TABLE 分析索引可以用ANALYZE INDEX命令。對於少於100萬的表,可以考慮分析整個表,對於很大的表,可以按百分比來分析,但是百分比不能過低,否則生成的統計信息可能不准確。可以通過DBA_TABLES的LAST_ANALYZED列來查看表是否經過分析或分析時間,索引可以通過DBA_INDEXES的LAST_ANALYZED列。
  
  下面通過例子來說明分析前后的速度對比。(表CASE_GA_AJZLZ大約有35萬數據,有主鍵)首先在SQLPLUS中打開自動查詢執行計划功能。(第一次要執行/RDBMS/ADMIN/utlxplan.sql來創建PLAN_TABLE這個表)
  
  SQL> SET AUTOTRACE ON
  SQL>SET TIMING ON
  
  通過SET AUTOTRACE ON 來查看語句的執行計划,通過SET TIMING ON 來查看語句運行時間。
  
  SQL> select count(*) from CASE_GA_AJZLZ;
  COUNT(*)
  ----------
  346639
  
  已用時間: 00: 00: 21.38
  
  Execution Plan
  ----------------------------------------------------------
  0 SELECT STATEMENT Optimizer=CHOOSE
  1 0 SORT (AGGREGATE)
  2 1 TABLE ACCESS (FULL) OF 'CASE_GA_AJZLZ'
  ……………………
  
  請注意上面分析中的TABLE ACCESS(FULL),這說明該語句執行了全表掃描。而且查詢使用了21.38秒。這時表還沒有經過分析。下面我們來對該表進行分析:
  
  SQL> analyze table CASE_GA_AJZLZ compute statistics;
  
  表已分析。
  
  已用時間: 00: 05: 357.63
  
  然后再來查詢:
  
  SQL> select count(*) from CASE_GA_AJZLZ;
  COUNT(*)
  ----------
  346639
  
  已用時間: 00: 00: 00.71
  
  Execution Plan
  ----------------------------------------------------------
  0 SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=351 Card=1)
  1 0 SORT (AGGREGATE)
  2 1 INDEX (FAST FULL SCAN) OF 'PK_AJZLZ' (UNIQ) (Cost=351
  Card=346351)
  …………………………
  
  請注意,這次時間僅僅用了0.71秒!這要歸功於INDEX(FAST FULL SCAN)。通過分析表,查詢使用了PK_AJZLZ索引,磁盤I/O大幅減少,速度也大幅提升!下面的實用語句可以用來生成分析某個用戶的所有表和索引,假設用戶是GAXZUSR:
  
  SQL> set pagesize 0
  SQL> spool d:/analyze_tables.sql;
  SQL> select 'analyze table '||owner||'.'||table_name||' compute statistics;' from dba_tables where owner='GAXZUSR';
  SQL> spool off
  SQL> spool spool d:/analyze_indexes.sql;
  SQL> select 'analyze index '||owner||'.'||index_name||' compute statistics;' from dba_indexes where owner='GAXZUSR';
  SQL> spool off
  SQL> @d:/analyze_tables.sql
  SQL> @d:/analyze_indexes.sql
  
  解釋:上面的語句生成了兩個sql文件,分別分析全部的GAXZUSR的表和索引。如果需要按照百分比來分析表,可以修改一下腳本。通過上面的步驟,我們就完成了對表和索引的分析,可以測試一下速度的改進啦。建議定期運行上面的語句,尤其是數據經過大量更新。
  
  當然,也可以通過dbms_stats來分析表和索引,更方便一些。但是我仍然習慣上面的方法,因為成功與否會直接提示出來。
  
  另外,我們可以將優化模式進行修改。optimizer_mode值可以是RULE、CHOOSE、FIRST_ROWS和ALL_ROWS。對於OLTP系統,可以改成FIRST_ROWS,來要求查詢盡快返回結果。這樣即使不用分析,在一般情況下也可以提高查詢性能。但是表和索引經過分析后有助於找到最合適的執行計划。
  
  三.設置cursor_sharing=FORCE 或SIMILAR
  
  這種方法是8i才開始有的,oracle805不支持。通過設置該參數,可以強制共享只有文字不同的語句解釋計划。例如下面兩條語句可以共享:
  
  SQL> SELECT * FROM MYTABLE WHERE NAME='tom'
  SQL> SELECT * FROM MYTABLE WHERE NAME='turner'
  
  這個方法可以大幅降低緩沖區利用率低的問題,避免語句重新解釋。通過這個功能,可以很大程度上解決硬解析帶來的性能下降的問題。個人感覺可根據系統的實際情況,決定是否將該參數改成FORCE。該參數默認是exact。不過一定要注意,修改之前,必須先給ORACLE打補丁,否則改之后oracle會占用100%的CPU,無法使用。對於ORACLE9i,可以設置成SIMILAR,這個設置綜合了FORCE和EXACT的優點。不過請慎用這個功能,這個參數也可能帶來很大的負面影響!
  
  四.將常用的小表、索引釘在數據緩存KEEP池中
  
  內存上數據讀取速度遠遠比硬盤中讀取要快,據稱,內存中數據讀的速度是硬盤的14000倍!如果資源比較豐富,把常用的小的、而且經常進行全表掃描的表給釘內存中,當然是在好不過了。可以簡單的通過ALTER TABLE tablename CACHE來實現,在ORACLE8i之后可以使用ALTER TABLE table STORAGE(B?R_POOL KEEP)。一般來說,可以考慮把200數據塊之內的表放在keep池中,當然要根據內存大小等因素來定。關於如何查出那些表或索引符合條件,可以使用本文提供的access.sql和access_report.sql。這兩個腳本是著名的Oracle專家 Burleson寫的,你也可以在讀懂了情況下根據實際情況調整一下腳本。對於索引,可以通過ALTER INDEX indexname STORAGE(B?R_POOL KEEP)來釘在KEEP池中。
  
  將表定在KEEP池中需要做一些准備工作。對於ORACLE9i 需要設置DB_KEEP_CACHE_SIZE,對於8i,需要設置b?r_pool_keep。在8i中,還要修改db_block_lru_latches,該參數默認是1,無法使用b?r_pool_keep。該參數應該比2*3*CPU數量少,但是要大於1,才能設置DB_KEEP_CACHE_B?R。b?r_pool_keep從db_block_b?rs中分配,因此也要小於db_block_b?rs。設置好這些參數后,就可以把常用對象永久釘在內存里。
  
  五.設置optimizer_max_permutations
  
  對於多表連接查詢,如果采用基於成本優化(CBO),ORACLE會計算出很多種運行方案,從中選擇出最優方案。這個參數就是設置oracle究竟從多少種方案來選擇最優。如果設置太大,那么計算最優方案過程也是時間比較長的。Oracle805和8i默認是80000,8建議改成2000。對於9i,已經默認是2000了。
  
  六.調整排序參數
  
  (1) SORT_AREA_SIZE:默認的用來排序的SORT_AREA_SIZE大小是32K,通常顯得有點小,一般可以考慮設置成1M(1048576)。這個參數不能設置過大,因為每個連接都要分配同樣的排序內存。
  
  (2) SORT_MULTIBLOCK_READ_COUNT:增大這個參數可以提高臨時表空間排序性能,該參數默認是2,可以改成32來對比一下排序查詢時間變化。注意,這個參數的最大值與平台有關系。
  
  七.調整其它幾個關鍵的性能參數
  
  很多人認為使用oracle數據庫,系統的默認參數就是最好的,其實不是這樣

====================================================================================================

● 配置和優化有什么不同

● 獲得最大的性能

● 配置操作系統

● 配置Oracle


Oracle 性能
● 調整和配置數據庫對象 
● 優化Oracle
最大化
如果你問很多Oracle DBA“你工作中最大的一部分是什么?”幾乎所有的回答都是“數據庫的配置和優化。”Oracle 是一種真正復雜和強大的產品,而且它的強大的能力在於它對每個單獨的數據庫配置都可以以最好的性能運行。本章講述我們配置和優化 Oracle 數據庫的方法,並提供了為站點實現一個高性能數據庫的指導方針。

大多數Oracle DBA 連續的、每天的職責是使 Oracle 數據庫獲得可能的最好性能。對於“性能”可能有許多定義,但是我們把性能定義為目標和在懷疑有問題的數據庫中執行一個典型操作需要的可以測量的時間。是的,這是一個太簡單的定義,它忽視了其他的測量尺度,如資源使用。但是讓我們正視它:我們期望數據庫盡可能地快,因此為了這個目的這是一個合理的定義。

整本書都是以Oracle 性能為主題寫的(參見附錄“DBA 使用的資源”以查看我們認為你應該注意的內容,注1),所以我們不能在一章中就闡述完復雜的Oracle 性能優化,我們希望提供一種直截了當的性能優化方法並提供能應用到各個不同安裝上的實際指南。

從物理和邏輯的實現、處理的事務類型及這些事務的性能需求方面來看,每個Oracle 安裝都是不同的,認識到這點很重要。結果是雖然一些廠商(包括 Oracle) 嘗試提供,但仍沒有一種自動的優化方法,而且也沒有單一的一套規則可以提供一種使數據庫性能最優的方法。然而,我們可以提供一種方法,在適當應用並結合DBA 知識和經驗的情況下,該方法將使任何給定的數據庫有好的性能。

注1:  我們尤其推薦Mark Gurry 和Peter Corrigan 的《Oracle Performance Tuning》第二 
  版(O'Reilly&Associates,1997)。 
46   

配置和優化有什么不同
使一個 Oracle 數據庫獲得最佳性能需要認真注意數據庫的配置和優化兩方面。這些術語經常交換使用,但是事實上,它們是兩個不同的任務,無可否認的是在它們之間有一少部分內容是重疊的。

配置是設置數據庫的物理和邏輯組件的過程,也是配置主機系統的過程,而優化是修改數據庫的內部行為的過程,以便操作以特定方式運行。整個過程某種程度上是循環的,因為合適的優化經常包含修改配置,然后再一次查看優化結果。圖 3-1 演示了配置和優化過程的基本步驟。

可以配置什么
能在一個 Oracle 數據庫中配置的一些項目如下:

● 影響系統進程分配的數據庫的組件,例如 : SQL*Net MTS(Multi-Threaded Server,多線程服務器)

並行查詢(Parallel Qry)
並行服務器(Parallel Server)


● 物理存儲的布局和大小 
● 數據庫對象的大小,如:

索引
回滾段
排序區
臨時表空間
重做日志


 
不是

圖 3-1:配置和優化過程

分區表
惟一索引(Index-only)表


● 內存的數量和分配,例如 :

數據庫緩沖區
重做日志緩沖區
共享池


可以優化什么

Oracle 數據庫可以優化的方面包括下列各項:

● 內存使用 
● 磁盤使用 
● SQL 語句執行
獲得最大的性能
使你的Oracle數據庫獲得最大的性能並不是一下子就可以做到的,這通常是大量辛苦的工作、思考和計划的結果。然而,從付出努力所得到的回報來看,是非常值得的,你的數據庫在最高效地運行,你的用戶高興,你也很滿意。

我們使性能最大化的方法是按自然層次分類的。需要從3 個不同方面,並按照順序來闡述。這3 個方面是:

● 操作系統配置 
● Oracle 資源配置 
● 對象創建和SQL 語句執行
這些方面不是互不相關的,實際上,對某方面的重要改變可能需要考慮其他方面。它們是順序依賴的,也就是說,直到你已正確配置和調整了操作系統,你才能使Oracle 達到很好的性能。同樣,查詢的快速執行取決於是否合理地配置了Oracle 環境。

每個Oracle數據庫的情況都是不同的,因此我們不能精確地告訴你該如何完成你的配置和優化目標,甚至你的目標是什么。我們要做的是為你提供一個我們已經成功的方法。

配置操作系統
這通常是容易的,因為那不是你的工作(在大部分情形下)! 在大多數安裝中,有系統管理員或管理者負責操作系統和硬件事情。這個系統管理員通常是硬件和操作系統軟件方面的專家,而且大多數DBA不用再管它。但在服從系統管理員專長的同時,這里有你必須確定的幾點:

● 應該充分利用物理內存,但是交換(swapping)(在交換內存環境中)不應該發生。把內存交換到磁盤的過程非常慢,因此如果系統需要更多的內存,就再買一些內存。尤其是要確定你沒有創建對於物理內存來說太大的SGA,因為SGA 交換將嚴重降低 Oracle 性能 
● CPU 在峰值時應達到100% 使用,但是進程不應該等待CPU 
● 磁盤和控制器應該運行在最佳容量(通常是最大值的60%~90% 或靠近最佳容量),而且沒有輸入/ 輸出等待。作為一個DBA,你也有一些對這個區域的控制,我們將會在本章后面描述 
● 網絡傳輸量不應該是一個瓶頸。考慮用主干網絡把服務器連接在一起,並且如有可能把客戶機/ 服務器通信和服務器/ 服務器通信分開 
● 盡量把Oracle 服務器放在一個單純的機器上,把用戶放到另外的機器上 
● 確保安裝了任何可能影響Oracle 的操作系統組件(包括補丁)
因為Oracle 是數據庫市場中的一個主要提供商,所以大多數硬件提供商中都有Oracle“專家”的職員,他們能提供可能影響Oracle 運行的硬件和操作系統方面的建議。要充分利用這些專業意見。

配置Oracle 
Oracle 的總性能受所安裝的組件以及這些組件如何配置的影響。Oracle 數據庫的高性能對於從運行在數據庫的事務中獲得最大性能是很必要的。這一節為配置SQL*Net/Net8、MTS、並行查詢(Parallel Qry)和並行服務器(Parallel Server) 提供了一般配置指南和一些具體建議。

配置指南
盡管每次安裝都會不同,但總有一些能應用到大多數數據庫的普遍適用的配置指南,而不管安裝組件的不同和數據庫應用的不同。下面章節將描述這些通用的指南。

查閱文檔

這看起來顯而易見,但還是有必要說。即使有經驗的DBA 也會從開始Oracle 安裝之前的快速閱讀相關文檔中受益。我們推薦你(至少)查閱下列文檔:

● 特定於硬件的IUG(安裝和用戶指南) 
● 服務器管理員指南 
● 版本發布說明(通常打包在介質中) 
● README 文件,通常可以在安裝介質中找到,它包含印刷文檔中可能沒有的最新信息
檢查資源需求

在開始安裝之前,確認是否有足夠的系統資源。與使用平台相關的IUG 資料包含了有關磁盤存儲和內存需求的全面信息。記住這些需求是最小需求,而實際上所需資源可能要更大,這與你做的其他配置有關。例如,如果你定義較大的SGA,就需要更多的內存。

尤其是要確保在你安裝Oracle 軟件(一般稱為ORACLE_HOME)的設備上有足夠的磁盤空間,以安裝所有的軟件和輔助文件。

檢查系統特權

大多數操作系統要求執行Oracle安裝的賬戶有特定的權限。一定要查看IUG進行確認,而且一定要確認系統管理員已經正確地進行了設置。注意這些特權可能包括在特定設備上創建目錄和文件的權利。

確定控制文件所在位置

Oracle 要求至少有一個控制文件。你應該設置至少兩個(通常更多)控制文件。這點極其重要,因為如果控制文件的所有拷貝丟失,你將不能掛接數據庫。因此要把控制文件放在不同的磁盤上,如有可能放置在不同的磁盤控制器上。

SQL*Net 配置
要對SQL*Net(Oracle7)和 Net8(Oracle8)進行配置,通常使用Oracle 網絡管理器或Net8助手。這通常在數據庫軟件安裝后,並且至少有一個Oracle 實例運行后進行,但是配置應該預先計划好。在開始SQL*Net/Net8 配置之前,你應了解如下內容:

● 網絡協議的類型:用來在你所在的環境中訪問Oracle 
● 命名模式:用來識別 Oracle 網絡節點 
● 你所在環境中的所有服務器、網關和多協議交換的名稱和網絡位置
一旦配置了SQL*Net/Net8,就要在每個服務器上設置如下文件:

listener.ora

控制SQL*Net 監聽進程的操作

tnsnames.ora

在未使用Oracle 命名軟件時,維護網絡中邏輯節點名稱(別名)和物理位置之間的關系

sqlnet.ora

控制Oracle 網絡操作的登錄(不是必需但強烈要求)

如果你使用多線程服務器,也需要在INIT.ORA 文件中進行配置,如下小節所示。

MTS 的配置
MTS(多線程服務器)在INIT.ORA 文件中進行配置,INIT.ORA 樣本的參數設置如下所示:

mts_dispatchers="ipc,1"
mts_dispatchers="tcp,1"
mts_max_dispatchers=10
mts_servers=1
mts_max_servers=10
mts_service=TEST
mts_listener_address="(ADDRESS=(PROTOCOL=ipc)(KEY=TEST))"
mts_listener_address="(ADDRESS=(PROTOCOL=tcp)(HOST=10.74.72.42)(PORT=1526))"


這個例子將配置一個MTS,它將處理與TEST 數據庫的TCP/IP 連接。它最多將啟動10 個調度程序,而且將創建多達10 個服務器進程。

注意: 記住,每個MTS進程都占用在INIT.ORA參數進程中指定總數中的數量,而且占用在操作系統級為Oracle 用戶開放最大的進程數中的數量。

並行查詢的配置
PQO(並行查詢選項)是 Oracle 的一個強大的特性,為了正確地使用它,一定要合理配置數據庫。並行查詢允許多CPU 系統把數據庫任務(通常是全表掃瞄)划分為能同時(並行)執行的一些片。為執行該任務要求如下:

● 通過設置INIT.ORA 中的PARALLEL_MAX_SERVERS 參數為一個大於0 的值來使能多個並行進程 
● 創建表空間必須使用多個數據文件,數據文件要分配到不同設備上。理論上講,分配給每個表空間的設備數等於系統中CPU 的數量 
● 利用並行查詢的表應該將其並行度值(使用CREATE TABLE 語句中的PARALLEL 子句)設置為包含表空間(表在其中創建)的數據文件的數目
並行服務器的配置
為了使用OPS,並行服務器允許由多個Oracle 實例共享一個 Oracle 數據庫,你可以通過在每個參與實例中使用INIT.ORA 參數來設定並行服務器特性,這些參數包括:

PARALLEL_SERVER

一定要設為TR,以使能OPS(只對於 Oracle8)。

INSTANCE_NUMBER

標識數據庫的實例。

ROLLBACK_SEGMENTS

指定每個實例私用的回滾段。也可以指定公用的回滾段,但是這不是必需的。

THREAD

識別與實例相關的重做日志線程。

GC_DB_LOCKS

實例鎖總數(僅在Oracle7 中)。

GC_FILES_TO_LOCKS

數據庫文件鎖的數目。

GC_LCK_PROCS

分布鎖的總數。

GC_ROLLBACK_LOCKS

回滾鎖的總數。

GC_SAVE_ROLLBACK_LOCKS

回滾保存鎖的數目(僅在Oracle7 中)。

GC_SEGMENTS 有影響空間管理行為的段的最大數目,該空間管理行為同時在段上執行(僅在Oracle 7 中)。

INSTANCE_GROUPS

把實例指定給一個或多個指定組(僅在Oracle8 中)。

LM_LOCKS

為鎖管理器配置的鎖數目(僅在Oracle8 中)。

LM_PROCS

鎖管理器的進程數(僅在Oracle8 中)。

LM_RESS

能被每個鎖管理器實例鎖定的資源數目(僅在Oracle8 中)。

OPS_ADMIN_GROUP

把實例分配給一個組來監視(僅在Oracle8 中)。

PARALLEL_INSTANCE_GROUP

標識要用來產生並行查詢從屬的並行實例組(僅在Oracle8 中)。

ROW_LOCKING

應該總被設定為ALWAYS。

SERIALIZABLE

應該設定成FALSE(僅在Oracle7 中)。

SINGLE_PROCESS

應該設定成FALSE(僅在Oracle7 中)。

關於這些參數的詳細信息參見第十二章“初始化參數”。因為OPS 是一個非常復雜的產品,所以你應該在嘗試配置並行服務器環境之前查閱《Oracle Parallel Server Concepts》和《Administration Guide》。在做配置時,記住以下幾點:

● 在 Unix 平台上,所有的數據文件一定要創建到裸分區中 
● 當創建一個數據庫時,只自動創建重做線程1,額外的線程需要顯式建立,而且你應指明重做日志屬於哪個線程 
● 雖然不是必需的,但確保實例數目和線程數目相同將避免混淆
注意: 術語“並行查詢”和“ 並行服務器”經常被混淆。並行查詢指單個Oracle 實例把操作(比如一個全表掃描)在相同主機上的多CPU 間分布並且合並結果的能力。另一方面,並行服務器是多個在不同主機上的Oracle實例共享一個物理數據庫的特性。在這種情況下,工作是通過把用戶在多個實例間分布或通過在多實例間產生並行查詢進程來在Oracle 實例間分布的。

調整和配置數據庫對象
要獲得最大的數據庫性能,數據庫對象的合理大小和配置是非常重要的。對象的合理大小是一個不斷進行的工作,隨着不斷創建對象和修改對象,也需要不斷地檢查對象特性並在需要時將其改變。以下與調整大小相關的問題的數值與性能成反比:

表空間碎片(tablespace fragmentation) 表空間碎片使許多無法使用的小延伸區分散在表空間中。當創建對象時,如果延伸區的INITIAL 或NEXT 的值設置不合理就會產生碎片。

行鏈(row chaining) 這個問題將導致單行的數據駐留在多個Oracle塊中,典型情況發生在PCTFREE 設置不足且表不斷進行更新時。

多個延伸區(multiple extent) 多個延伸區,可能導致一個特定對象的數據分散在一個或幾個數據文件之中,這是由在創建對象時指定了不合適的INITIAL或NEXT延伸區大小而引起的。這個問題可能會在MAXEXTENTS 參數被允許為默認值時變得很嚴重,因為嘗試分派一個超過那個數目的延伸區將導致失敗。

日志等待當寫日志緩沖區記錄到一個日志文件或當日志文件切換時,日志等待將引起一個進程等待,這時日志等待能大大增加處理時間。這通常由日志文件數目太少和日志文件太小等原因引起。

擴展一個回滾段失敗這樣的失敗(能引起一個事務回滾)是由於沒有分配充足的回滾段數目,或者是由於分配的回滾段不夠大。

下列各節講述了可以避免這些性能問題的一些指南和建議。

表是 Oracle 數據庫中數據存儲的基本單位,因此表的配置和由此產生的性能將對數據庫總體性能產生很大的影響。下面是表配置的一些指導方針:

● 試着估計一個表將多大,並且分配一個足夠大的初始延伸區來存放整個表。然而,如果你正在使用並行查詢,則應跨越不同的數據文件來分配總的空間,使分配的延伸區數目和表的並行度相等 
● 考慮使用多個表空間,每個表空間對應於不同大小或類型的表。例如,你可能有3 個表空間:LARGE_DATA、MEDIUM_DATA 和SMALL_DATA,每個會用來存儲大小不同的表。如果你使用多個表空間,要確保把每個表分配到恰當的表空間中 
● 確保分配一個DEFAULT TABLESPACE 給每個用戶。如果沒有分配,Oracle 將使用SYSTEM 表空間作為默認值 
● 如果可能,保證INITIAL和NEXT 延伸區大小總是相同大小的單元的整數倍,例如,是 512K 的整數倍。這樣,延伸區將是統一的大小,而且會比較容易分配額外的延伸區,而不引起表空間碎片。如果可能,在一個表空間中可以使用大小相同的延伸區 
● 設定PCTINCREASE參數為 0,為了防止延伸區分配失控和保持統一的延伸區大小。 
● 設定MAXEXTENTS 參數為UNLIMITED。這將防止延伸區用完,因為多個延伸區對它們產生很小的性能影響(雖然廣泛分布的延伸區對性能有負面影響)。這樣做可以防止錯誤,但是不要把它作為INITIAL 大小的替代 
● 如果表沒有更新,則設定PCTFREE 為0。如果表有更新,則估計行的列的增長程度,並分配一個PCTFREE 來防止塊鏈接,而在塊中沒有過多的未使用空間 
● 如果有很多事務同時訪問表,將INITRANS 設定為一個大於1(默認的)的數 
● 將 MAXTRANS 設定為在預期表上同時訪問的最大數目。一個較小值將會導致一個或多個事務等待前一個事務完成
索引
正確使用索引可以使性能大大提高,這是任何Oracle 單一特性所不能做到的。雖然許多性能提高獲益於優化 SQL 語句(見第八章“查詢優化”),但我們也提供一些配置指南:

● 為索引創建一個單獨的表空間,並且保證這個索引表空間的數據文件與包含索引表的表空間的數據文件不在同一個磁盤上 
● 試着去估計索引的大小而且分配一個足夠的INITIAL延伸區來存儲整個索引,除非你正在使用並行查詢,否則在這種情況下,你應該在與索引的並行度相同的數據文件之間分配總的空間 
● 如果可能,保證INITIAL和NEXT 延伸區大小總是相同大小的單元的整數倍,例如,是 512K 的整數倍。這樣,延伸區將會是統一的大小,而且會比較容易分配額外的延伸區而不引起表空間碎片 
● 設定 PCTINCREASE 參數為0 以防止延伸區分配失控並保持統一的延伸區大小 
● 設定 MAXEXTENTS 參數為UNLIMITED。這將防止延伸區用完,而多個延伸區可能產生的性能影響很小(雖然廣泛分布的延伸區對性能有負面影響)。這樣做可以防止錯誤,但是不要把它作為INITIAL 大小的替代
回滾段
Oracle 用回滾段來維護數據的一致性,允許事務的取消或回滾。回滾段使用很多的輸入/ 輸出,下面是配置回滾段的一些指導方針:

● 為回滾段創建一個單獨的表空間,如果可能,把這個表空間的數據文件放在一個與其他數據文件不同的磁盤上 
● 永遠不要在SYSTEM 表空間中創建回滾段(除了在數據庫創建期間需要的臨時回滾段以外,見第二章“安裝”) 
● 確保為回滾表空間分配了足夠大的空間,以允許回滾段為了適應大的更新事務來按照需要增長空間。記住批事務容易產生很大的回滾段 
● 總是保持回滾段的INITIAL 和NEXT 延伸區使用相同的數值(在CREATE TABLESPACE 語句中的DEFAULT STORAGE 子句中定義)。為回滾段分配大小相等的塊可以防止空間碎片 
● 記得每個回滾段必須至少有兩個延伸區,因此段的初始大小實際上是INITIAL + NEXT 的總和
● 定義一個OPTIMAL值,以便使為了延伸適應一個大事務而增長的回滾段可以回縮到一個合理的大小。然而,不要讓這個值太小,否則會浪費時間來為回滾段分配額外的延伸區
排序區
Oracle 使用INIT.ORA 參數SORT_AREA_SIZE 來為數據排序分配內存。當一個排序不能夠在內存中完成時,Oracle 使用數據庫中的臨時段,但這非常慢。應當小心平衡SORT_AREA_SIZE,因為大的排序區可以通過減少輸入/ 輸出來顯著增加性能,但是這將用光內存並引起分頁。

注意: 記住這個參數應用到每個用戶進程。每個執行排序的用戶進程都將分配 SORT_AREA_ SIZE 內存。因此,如果 SORT_AREA_SIZE 被設定為/MB,而有100 個用戶進程正在執行排序,那么將分配總數為100MB 的內存。

臨時表空間
如果沒有為執行排序的用戶進程分配足夠的內存,那么Oracle 將通過為用戶在TEMPORARY TABLESPACE參數指定表空間中創建臨時段來在磁盤上執行排序。除此之外,臨時段用來執行復雜查詢,如連接、UNION、MINUS 和索引創建。臨時區的指南如下:

● 為臨時段創建一個單獨的表空間(通常叫做 TEMP),如果可能,把這個表空間對應的數據文件放在一個單獨的磁盤上 
● 在CREATE TABLESPACE命令的DEFAULT STORAGE子句中指定INITIAL 和NEXT 參數。把兩者的值設為相等,以消除空間碎片,在 TEMP 表空間中極易產生碎片,因為在那里不斷地創建並刪除對象 
● 要確保為每個用戶指定一個TEMPORARY TABLESPACE。如果沒有指定,Oracle 將把SYSTEM 作為默認的表空間,而這樣對性能有負面的影響
重做日志
重做日志,也稱聯機重做日志文件,對 Oracle 的失效恢復能力至關重要。重做日

志的適當配置不但對數據庫的總體性能很關鍵,而且對恢復數據庫的能力也很重要(見第四章“防止數據丟失”)。相關指南如下:

● 使用Oracle 內嵌的鏡像特性,把重做日志文件的多組放在不同的磁盤上 
● 分配足夠的重做日志文件以便Oracle 無須為了重復使用一個文件而等待它。Oracle 至少要求有兩個重做日志文件,但是4 個或更多個是必要的 
● 分配的重做日志文件要足夠大以防止太多的日志文件切換,但又要適當的小以保證當前聯機日志文件失效時很好地恢復。如果文件較小,可能恢復已經歸檔的所有事務,而大的日志文件使數據庫有可能丟失更多的事務 
● 設置INIT.ORA參數 LOG_CHECKPOINT_INTERVAL值大於重做日志文件的大小,這樣將避免檢查點(checkpoint)進程,直到日志文件滿為止(引起一個檢查點進程)。這個參數以數據庫塊來表達
警告: 記住一個日志切換將導致從SGA 將臟緩沖區(例如有更新)寫入到磁盤。

● 如果你正在運行Oracle7,考慮設定INIT.ORA 參數CHECKPOINT_PROCESS 為TR。這么做將創建一個執行檢查點進程的單獨進程,而並非由LGWR(日志寫入進程)處理。見第十章“Oracle 實例”,可以了解更多信息

歸檔日志目的地
在配置方面一個經常需要注意的問題是要保證歸檔日志目的地有足夠的空間。如果數據庫正在歸檔日志模式中運行,那么當一個聯機重做日志文件填滿時,Oracle 的ARCH進程將復制這個文件的內容到INIT.ORA參數ARCHIVE_LOG_DEST指定的目錄。如果目的地太小,ARCH 就不能復制日志文件,而一旦所有的聯機日志文件滿,整個數據庫就會停止,直到這個問題解決。有經驗的DBA 已經意識到這種情況,這種情況大多數在半夜發生,就像REM 休眠一樣。

優化 Oracle 
或許DBA 的工作沒有哪一方面能像優化這樣消耗時間。成功的Oracle 優化既要求知識又要求經驗,挑戰和挫敗也同時存在。整卷都在寫Oracle優化(參見附錄“DBA 使用的資源”),但我們不能在一節中包括優化的所有方面。相反,正如我們前面提到的,我們將列出可以應用到各種情況的優化方法的大綱。

結構化優化方案
Oracle 數據庫的成功優化需要仔細的、有規則的方案。像整體系統配置一樣,優化一定要包括下列各項:

● 硬件和操作系統性能● Oracle 實例性能
● 單獨的事務(SQL)性能
這些方面應該按順序進行,因為沒有硬件和操作系統的良好優化,Oracle 的性能優化是不可能的。沒有數據庫的有效運行,一個單獨的SQL語句不可能很好地被優化。優化這些方面中的任何一方面時,都包括3 個步驟:

1. 測量目前的性能。 
2. 做適當的變化。 
3. 評估結果。 
警告:對Oracle實例的一些改變可能引起對操作系統環境的改變。比如,分配附加的數據庫緩沖區可能導致操作系統開始分頁,而這可能要求額外的操作系統優化來消除。

優化進程幾乎總是反復的。也就是說,在完成3 個步驟之后,DBA 必須回到第一步驟並且重復這個過程。這將一直持續到不會再有性能改善為止。

Oracle 實例優化
Oracle 實例層的大多數性能的提高將通過兩個方面達到: 內存使用和磁盤輸入/ 輸出。

內存使用

基於內存的操作比磁盤操作快得多(有時成千上萬倍),這一點是不值得驚訝的。結果將導致用內存訪問數據來代替磁盤輸入/ 輸出,以使性能得到巨大的提高。相關的3 個主要方法描述如下:

分配額外的DB_BLOCK_B?RS 這或許是改善總體性能的單一的最有效的方法,特別是在查詢上。更多的數據庫緩沖區允許更多的數據塊數據保持在內存中,因此可以按內存速度訪問包含在這些塊中的數據,而不需要磁盤輸入/ 輸出。緩沖區是由INIT.ORA 參數

DB_BLOCK_B?RS 來分配的,它的數值是要分配的數據塊緩沖(block b?r)數目。因此,如果數據庫塊大小是8192,每個DB_BLOCK_B?R 將是8192 字節。注意改變DB_BLOCK_B?RS 值后直到下次數據庫重啟才生效。

注意: 注意不要分配太多的DB_BLOCK_B?RS以導致操作系統開始分頁,分頁將消除你獲得的性能,而且將對整體性能產生負面影響。

分配額外的共享池共享池大小由INIT.ORA的參數SHARED_POOL_SIZE 控制,它指定了以字節為單位的共享池大小。共享池的主要內容是字典緩存區(dictionary cache)和共享SQL 區(shared SQL area)。由於字典緩存區的各部分組件由Oracle 自動分配,所以共享池的任何增加都會使字典緩存區和共享SQL 區增加。

共享SQL 區包含最近執行的SQL 語句的拷貝,連同相關信息,如它們的執行計划。共享池越大,特定SQL 語句被解析並且駐留在共享SQL 區就越有可能,因此節省了需要再次處理這個語句的時間。在相同的SQL語句被多次執行且對速度有要求的事務處理系統中,這是個特別重要的值。

分配更多的日志緩沖區空間日志緩沖區是用來存儲將要寫到聯機重做日志文件上的數據的。日志緩沖區的大小由INIT.ORA 參數LOG_B?R 控制,其數值以字節表示。為日志緩沖區分配更多的內存,將減少磁盤輸入/ 輸出,尤其是在事務特別長或數量很多時。

磁盤輸入/ 輸出

磁盤訪問是任何計算機系統上的最慢的操作。作為一個數據庫系統,Oracle 的存儲和訪問數據非常依賴磁盤訪問。考慮一個典型的更新一個表的一行的SQL 語句,將發生下列各項操作:

1. 讀數據字典獲得關於表和正在被操作的行的信息。 
2. 讀適當的索引來定位要更新的行。 
3. 讀包含行的數據塊。 
4. 寫回滾信息到一個回滾段。 
5. 寫更新信息到聯機日志文件。 
6. 重寫數據塊。 
7. 重寫索引塊。 
雖然一些操作可以通過有效使用內存消除,正如我們前面提到的,但所有這些操作都潛在地要求磁盤輸入/ 輸出。通過盡可能使磁盤輸入/ 輸出有效,可增強總性能。使磁盤輸入/ 輸出最大值的基本指南如下:

● 只要可能,分離輸入/輸出操作到單獨的磁盤上。這樣,在執行另外一個時,不需要等待一個磁盤操作完成。例如,如果回滾段和日志文件在相同的磁盤上,需要寫回滾記錄,然后磁盤磁頭需要移動到日志文件記錄要寫的那部分磁盤。這是非常耗時的 
● 把高輸入/ 輸出的磁盤放在不同的控制器上。現代的控制器可以處理有限數目的並發操作,但是盡可能使用更多的控制器將消除任何控制器等候並加速性能 
● 把最忙的文件和表空間(例如,日志文件、回滾段、一些索引)放在最快的可用磁盤上
關於RAID 的注釋

磁盤技術的最新發展使 RAID(廉價磁盤冗余陣列)成為許多系統上很常用的一個選項。通常,當使用術語 RAID 時,硬件管理員會立刻想到RAID 5(或 RAID-5), 它允許多個磁盤結合成一個大的設備。通過分配一個磁盤設備來存儲冗余數據,一個 RAID-5 磁盤陣列可以承受陣列中的任何單一磁盤失效,並且經常是熱交換的,也就是當一個磁盤失效時,其他的磁盤繼續工作的同時更換這塊磁盤,而不必關閉系統。

事實上RAID-5 是非常強大且廉價的。當配置Oracle 數據庫時,在大多數情況下要避免使用這種技術。這可能聽起來很刺耳,但是事實上雖然RAID-5 成本較低,而且提供了很好的數據保護級別,但是它的磁盤輸入/輸出花費很高。尤其是在RAID5 陣列上的寫操作要比在單一磁盤上的寫操作慢得多。RAID-5 陣列的一個好的替代品是RAID1,就是大家都知道的磁盤鏡像。雖然比RAID-5(一半磁盤用來存儲冗余數據)更貴,但是RAID-1提供了完全的數據保護,而在輸入/ 輸出效率上沒用降低。

警告: RAID-1 要求有足夠的硬件資源。尤其是由於每次寫操作實際都要對磁盤進行兩個寫操作,所以控制器上的負荷是非RAID 的兩倍。

現在性能最好的RAID 是RAID-0+1,有時叫做 RAID-10。RAID 的這個級別在多個驅動器上結合了帶有數據條帶(RAID-0)的鏡像磁盤(同RAID-1),這可以消除等待磁盤頭定位的延遲。而這在其他的RAID 控制器中都沒有,RAID-0+1 是值得考慮的。

操作系統條帶化

許多操作系統提供了在多個磁盤設備中磁盤扇區的自動條帶化。條帶化允許磁盤輸入/ 輸出連續,而沒有頭定位的延遲。雖然這個技術提供了比在一個單一磁盤上更好的性能,但也有一些缺點: 結合多個磁盤為一個單一的條帶單元意味着DBA不能夠控制單個文件在單獨磁盤設備的位置。如果你的系統上只有少數的大磁盤,你應該考慮操作系統條帶化,但是多磁盤設備或多 RAID-0+1 陣列通常會從Oracle 產生更好的性能。

Oracle 條帶化

作為DBA,通過小心地把數據文件分配到單個磁盤設備或 RAID-0+1陣列,你可以達到與操作系統條帶化相似的結果。例如,建立跨越4 個磁盤的Oracle 條帶化需做下列各項工作:

● 創建一個有4 個數據文件的表空間,每個位於一個不同的磁盤設備上 
● 在表空間中創建對象,指定MINEXTENTS 4。Oracle 將把4 個延伸區分配到4個數據文件上,這樣就實現了條帶化。這個行動不是自動的,還需使用ALTER TABLE ... ALOCATE EXTENT 命令
Oracle 條帶化技術非常強大,尤其和並行查詢結合的時候,將通過多CPU 處理查詢過程。

SQL 優化
假如主機服務器和操作系統正在你的站點順利運行,而且你配置並優化了Oracle, 使其在最好狀態運行,但是你的重要應用程序仍然運行很差。不幸的是這種情況經常發生。解決方法是通過檢查和優化正在被執行的SQL 語句來優化應用程序。

SQL 優化這個題目值得寫一本書。實際上,在市場上有很不錯的書闡述得比這里更為詳細。我們建議你檢查附錄中列出的DBA資源。在這小節中,我們將為你提供優化SQL 語句的一些概要建議和指南。

查詢處理

第八章“查詢最優化”描述了Oracle 如何為一個特定的SQL 語句創建一個計划。Oracle 現在用兩個方法中的一個來決定該如何執行一個SQL 語句:

基於規則的方法應用一個標准的、固定的(但是經常有效的)規則集到語句中。

基於費用的方法

考慮由一個SQL語句(連同可得的索引一起)引用的對象的可用統計信息,並

基於這些統計建立一個計划。

優化一個SQL語句的關鍵是理解Oracle查詢優化器如何工作和知道怎樣改變Oracle 的行為,以便它能更有效地處理語句。

當然,在優化一個SQL 語句之前,必須知道它在做什么和如何做。今天市場上的許多工具將有助於完成這個工作,而且最有用的工具之一是SQL*Plus中的EXPLAIN PLAN 命令。通過創建一個計划表(通常為PLAN_TABLE)並且檢查EXPLAIN PLAN 語句的結果,你會容易地看到Oracle 如何執行一個特定的語句。例如,SQL 語句:

SELECT ename,loc,sal,hiredate
FROM scott.emp, scott.dept
WHERE emp.deptno=dept.deptno;


可用下面的命令解釋:

EXPLAIN PLAN SET STATEMENT_ID='DEMO' FOR
SELECT ename,loc,sal,hiredate
FROM scott.emp, scott.dept


WHERE emp.deptno=dept.deptno;


存儲在PLAN_TABLE 中的結果可以通過下面的簡單查詢看到:

SELECT LPAD(' ',2*level) || operation || '' || options || ' '||


object_name EXPLAIN_PLAN
FROM plan_table
CONNECT BY PRIOR id = parent_id
START WITH id=1


看起來像這樣:

EXPLAIN_PLAN


NESTED LOOPS
TABLE ACCESSFULL DEPT
TABLE ACCESSFULL EMP


這個計划表明將使用全表掃描來對DEPT 和EMP 表訪問。這對像EMP 和DEPT 一樣的小表很好,事實上,我們想要它們全表掃描,因為表將緩存到內存中,並且不需要磁盤輸入/ 輸出(至少在第一次運行之后)。然而,如果表很大,這個查詢將進行很長時間,所以我們想改變查詢執行的方式。

有3 個基本方法可以改變Oracle 查詢優化器的行為:

● 在執行查詢時提供一個或多個索引來用 
● 重寫SQL 來使用一個更為有效的方法 
● 以提示(hint)的形式提供查詢優化器指導
如果我們試第一選項而且在EMP(deptno)上增加一個索引,計划將改變為:

EXPLAIN_PLAN


NESTED LOOPS
TABLE ACCESSFULL DEPT
TABLE ACCESSBY ROWID EMP


INDEXRANGE SCAN EMPDEPT_IX


現在你能看見Oracle 使用索引通過ROWID 來從EMP 取回行,ROWID 是從新創建的索引中獲得的,而不再需要全表掃描。通常使用SQL 會有不止一種實現一個特定功能的方法,在確定使用正確的SQL 語句之前嘗試幾種不同的方法(有適當的基准)是一種很好的實踐方式。第八章“查詢最優化”提供了關於SQL 優化的更詳細信息。

其他有用的優化特性
Oracle 通過增加提高性能的新特性來不斷改良數據庫產品。檢查即使只有很小更新的Oracle 版本注釋是很重要的,因為這其中可能就包含了新的性能特性。你可能覺得有用的一些特性和工具列表如下:

分區表(partitioned table)

從Oracle8 開始分區表就允許在多個子表上創建表,每個子表包含了表數據的一個特定子集。例如,一個表可以按年分區,所有1998 年的數據在一個分區中,所有1999 年的數據在另一個分區中等等。分區對大的表特別有用,因為對包含在一個可識別的子集中的數據進行查詢可以在對應的分區中操作,而不用訪問其他的分區。例如,更新 1999 年的記錄只要求Oracle 在1999 年的分區上執行輸入/ 輸出操作。可在CREATE TABLE 語句中指定分區。為了使用這個特性,你必須:

● 標識將要定義分區的數據字段(例如sales_year) 
● 在CREATE TABLE ... PARTITION BY RANGE 子句中指定值的范圍 
● 為表的每個分區指定一個另外的表空間(為了得到最好的性能,把表的每個分區放置在不同的磁盤上)。注意單獨的表空間不是必需的,但是這種做法可以允許表的一個分區脫機,而維持訪問表的剩余部分分區表通常應該伴隨着相應的分區索引,如下: 
● 使用CREATE INDEX 命令的LOCAL 關鍵字來告訴Oracle 為索引表的每個分區創建一個單獨的索引 
● 使用CREATE INDEX 命令的GLOBAL 關鍵字,以便告訴Oracle 使用不會對應到索引表分區的值來創建一個單一索引。全局(GLOBAL)索引也可以分區
惟一索引表(index-only table)

在某些情況下,正常時存儲在一個表中的所有數據可以存放在一個索引中,這樣表就沒必要了。從Oracle8 開始,一個惟一索引表就使數據按照主鍵列排序。對這種類型的對象有一些限制:

● 由於數據沒有存儲在一個表中,所以沒有 ROWID 可用 
● 必須為表定義一個主鍵 
● 不能創建其他的索引,只有主鍵可以被創建為索引
惟一索引表通過使用CREATE TABLE命令的ORGANIZATION INDEX子句創建。

位圖索引(bitmap index)

當被索引的數據有低基數(cardinality)時(也就是說索引列有相對較少的確定值時),創建位圖索引可以大大改善性能。位圖索引的一個好的例子就是性別(GENDER),它只有兩個值“M”或“F”。對於銷售總額(SALES_AMOUNT),將

不適合建立位圖索引,因為它對於每行都可能有一個不同的值。

創建一個位圖索引類似於創建一個標准的索引,你可以在CREATE INDEX 語句中包括關鍵字BITMAP。例如,在EMPLOYEE_MASTER 表的GENDER 列創建一個位圖索引,指定下列語句:

CREATE BITMAP INDEX empmast_ix ON employee_master(gender);


臨時表空間

Oracle7 引進了臨時表空間的概念,這專門為Oracle 的排序段使用。通過消除連續不斷地分配和釋放排序空間的空間管理操作,當排序很大以致內存不能容納時,所有使用排序的操作將得到性能的提高。這在運行OPS 的時候尤為重要。

注意: 一個臨時表空間只能用於排序段,不要在臨時表空間中創建永久對象。

要創建一個臨時表空間,需要在CREATE TABLESPACE 語句中使用關鍵字TEMPORARY。例如,下面語句將創建一個叫做TEMP 的臨時表空間:

CREATE TABLESPACE TEMP
DATAFILE '/disk99/oracle/oradata/TEST/temp01.dbf' SIZE 50M
DEFAULT STORAGE(INITIAL 64K NEXT 64K MAXEXTENTS UNLIMITED)


TEMPORARY;


一個已存在的非臨時表空間可以轉變為臨時表空間,如果它不包含永久對象,可使用下面SQL 語句進行轉換:

ALTER TABLESPACE tablespace TEMPORARY;


不能恢復的操作

由Oracle 7.2 開始,在創建表或索引時就可能不寫重做日志記錄。這個選項提供了較好的性能,因為需要的輸入/ 輸出少了很多。要利用這個特性在對象創建語句中指定UNRECOVERABLE(Oracle7語法)或 NOLOGGING(Oracle8 語法)。例如,你想使用數據庫鏈接從另外一個數據庫移動數據可使用下面這個語句:

INSERT INTO newtable
SELECT * from oldtable@oldlink;


這個方法當然會奏效,但是將為每次插入創建重做日志記錄,這將浪費資源。可以用下面語句完成相同的任務:

CREATE TABLE newtable AS
SELECT * from oldtable@oldlink
NOLOGGING;


當重建索引的時候,NOLOGGING 選項將特別有用。NOLOGGING 關鍵字可以大大減少索引創建的時間。SQL 語句與下面語句相似:

CREATE INDEX indexname ON table(column)
NOLOGGING;


注意,如果在執行一個不能恢復的語句之后,在某點發生了系統失效,你將不能使用回滾機制來恢復這個事務,你必須意識到一個系統失效已經發生並且要重新運行語句。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM