ORACLE中dual的詳解及其故障恢復

什麼是dual呢?
首先,dual是屬於sys用戶的;
它只有一個X varchar2(1)的列;
查詢這個虛擬的列不會產生邏輯的IO;
dual是oracle中的一個實際存在的表,任何用戶都可讀取,常用在沒有目標表的select語句塊中
以下是oracle manual中對dual的說明:
The table named DUAL is a small table in the data dictionary that Oracle and user-written programs can reference to guarantee a known result. This table has one column called DUMMY and one row containing the value X.
這個名稱爲dual的表是位了保證oracle和用戶程序能夠引用一個已知的值。這個表只有名稱爲DUMMy的僞列,而且只有一行其值爲X。

下面我們通過一些例子來說明dual的結構和功能
測試環境:
rhel5.4 32bit
oracle 10.2.0.1.0

DUAL表的用途
1、查看當前連接的用戶
SQL> select user from dual;
2、查看當前的日期
SQL> select sysdate from dual;
SQL> select to_char(sysdate,'yyyy/mm/dd hh24:mi:ss') from dual;
3、當做簡單的計算器使用
SQL> select 1+2 from dual;
4、查看序列的值
SQL> create sequence test_seq increment by 1 start with 1;
SQL> select test_seq.nextval from dual;
SQL> select test_seq.currval from dual;

關於dual表的深入測試和分析
dual表就是一個一行一列的表,如果向這個表中執行insert、delete、truncate操作,就會導致許多程序出現問題。結果也會因爲sqlplus、pl/sql等工具的不同而不同
1、dual的結構
SQL> select owner,object_name,object_type from dba_objects where object_name like '%DUAL%';
OWNER      OBJECT_NAM OBJECT_TYP
---------- ---------- ----------
SYS        DUAL       TABLE
PUBLIC     DUAL       SYNONYM
在查看一下DUAL表的結構
SQL> set long 1000
SQL> select dbms_metadata.get_ddl('TABLE','DUAL','SYS') from dual;
CREATE TABLE "SYS"."DUAL"
(
"DUMMY" VARCHAR2(1)
)
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(
INITIAL 16384 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
)
TABLESPACE "SYSTEM"
SQL> select dbms_metadata.get_ddl('SYNONYM','DUAL','PUBLIC') FROM DUAL;
CREATE OR REPLACE PUBLIC SYNONYM "DUAL" FOR "SYS"."DUAL"
很是困惑,ORACLE爲什麼要用VARCHAR(1)型,用CHAR(1)難道不好麼?從這樣的表結構來看,DUAL表設計的目的就是要儘可能的簡單,以減少檢索的開銷。
dual表是建立在system表空間的,一個是因爲dual表時sys這個用戶建立的,默認的表空間也就是system;另外一個原因是經常被查詢的表和用戶表分開來存放,對系統的性能不會造成過多的影響
有了創建表、同義詞這些還是不夠的,dual是在sys這個方案下面的,因此別的用戶是無法查看這個表的,還是需要授權的:
SQL> grant select on sys.dual to public with grant option;
事實上,dual表中的數據和oracle的數據庫環境有着十分重要的關係(oracle不會爲此而癱瘓,但是有不少的存儲過程以及一些查詢將會無法完成
2、dual的內容
SQL> select count(*) from dual;
D
-
X
插入一條數據,再查詢,只返回一行記錄:
SQL> select count(*) from dual;
  COUNT(*)
----------
         1
SQL> insert into dual values('Y');
SQL> insert into dual values('Z');
SQL> insert into dual values('M');
SQL> commit;
SQL> select count(*) from dual;
  COUNT(*)
----------
         1
SQL> select * from dual;
D
-
X
網上的一些資料表示這個count(*)在進行insert的時候會發生一些變化:在insert之後,再count(*)的時候會顯示累加的數據,在執行一次select *之後,這個值會再次的變爲1。
不過在我的測試中,(不論windows平臺,還是在linux平臺)。這個count(*)和select *的數據數目,無論如果insert都不會發生變化。不曉得是不是和數據庫的版本有關係?
在這裏我們假設說,網上的例子中的情況時可以有的,即dual表中可以有多條記錄。這樣通常會引起問題,如果使用類似於select sysdaba into v_sysdate from dual;的pl/sql語句來獲取時間或者其他信息,oracle就會拋出TOO_MANY_ROWS(ORA-01422)異常
3、truncate dual表
SQL> truncate table dual;
SQL> select count(*) from dual;
  COUNT(*)
----------
         1
SQL> select * from dual;
no rows selected
SQL> select sysdate from dual;
SYSDATE
---------
23-MAY-12
在這裏我們可以看到當我們截斷表之後,還是可以根據dual來查詢到sysdate,這個,,,和網絡上的相關資料也不大一樣!
4、drop table
dual表可以執行插入、更新、刪除操作,還可以執行drop操作,但是在執行drop之後會導致系統不能用,數據庫起不起來,會報Database startup crashes with ORA-01092錯誤
如果dual不幸被刪除了,,,
SQL> drop table dual;
這個時候如果執行對dual的select操作,會警告說同義詞dual找不到目標對象,因爲我們只是刪除了dual表,還有一個dual的同義詞呢
SQL> shutdown immediate;
SQL> startup
ORACLE instance started.
Total System Global Area  285212672 bytes
Fixed Size                  1218992 bytes
Variable Size              83887696 bytes
Database Buffers          197132288 bytes
Redo Buffers                2973696 bytes
Database mounted.
ORA-01092: ORACLE instance terminated. Disconnection forced
SQL> startup mount
SQL> create pfile from spfiel;
SQL> shutdown immediate;
在剛纔新建的pfile中新增加參數:replication_dependency_tracking=FALSE,將spfile重命名下,然後startup
SQL> startup
ORACLE instance started.
Total System Global Area  285212672 bytes
Fixed Size                  1218992 bytes
Variable Size              83887696 bytes
Database Buffers          197132288 bytes
Redo Buffers                2973696 bytes
Database mounted.
Database opened.
啓動成功!然後我們需要重建dual表
SQL>CREATE TABLE "SYS"."DUAL"
(
"DUMMY" VARCHAR2(1)
)
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(
INITIAL 16384 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
)
TABLESPACE "SYSTEM"
SQL> insert into dual values('X');
SQL> commit;
SQL> shutdown immediate;
將spfile換回原來的名字
SQL> startup
SQL> grant select on dual to public;
SQL> select * from dual;
D
-
X
SQL> select sysdate form dual;
SYSDATE
---------
23-MAY-12
SQL> conn scott/tiger
SQL> select sysdate from dual;
SYSDATE

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章