(轉)ORACLE之常用FAQ V1.08

Q]怎麼樣創建使用虛擬索引
[A]可以使用nosegment選項,如
create index virtual_index_name on table_name(col_name) nosegment;
假如在哪個session需要測試虛擬索引,可以利用隱含參數來處理
alter session set "_use_nosegment_indexes" = true;
就可以利用explain plan for select ……來看虛擬索引的效果
利用@ $ORACLE_HOME/rdbms/admin/utlxpls查看執行計劃
最後,根據需要,我們可以刪除虛擬索引,如普通索引一樣
drop index virtual_index_name;
注重:虛擬索引並不是物理存在的,所以虛擬索引並不等同於物理索引,不要用自動跟蹤去測試虛擬索引,因爲那是實際執行的效果,是用不到虛擬索引的。

[Q]怎樣監控無用的索引
[A]Oracle 9i以上,可以監控索引的使用情況,假如一段時間內沒有使用的索引,一般就是無用的索引
語法爲:
開始監控:alter index index_name monitoring usage;
檢查使用狀態:select * from v $object_usage;
停止監控:alter index index_name nomonitoring usage;
當然,假如想監控整個用戶下的索引,可以採用如下的腳本:
set heading off
set echo off
set feedback off
set pages 10000
spool start_index_monitor.sql
SELECT 'alter index '||owner||'.'||index_name||' monitoring usage;'
FROM dba_indexes
WHERE wner = USER;
spool off
set heading on
set echo on
set feedback on
------------------------------------------------
set heading off
set echo off
set feedback off
set pages 10000
spool stop_index_monitor.sql
SELECT 'alter index '||owner||'.'||index_name||' nomonitoring usage;'
FROM dba_indexes
WHERE wner = USER;
spool off
set heading on
set echo on
set feedback on

[Q]怎麼樣能固定我的執行計劃
[A]可以使用OUTLINE來固定SQL語句的執行計劃
用如下語句可以創建一個OUTLINE
Create oe replace outline OutLn_Name on
Select Col1,Col2 from Table
where ……
假如要刪除Outline,可以採用
Drop Outline OutLn_Name;
對於已經創建了的OutLine,存放在OUTLN用戶的OL $HINTS表下面
對於有些語句,你可以使用update outln.ol $hints來更新outline
如update outln.ol $hints(ol_name,'TEST1','TEST2','TEST2','TEST1)
where ol_name in ('TEST1','TEST2');
這樣,你就把Test1 OUTLINE與Test2 OUTLINE互換了

假如想利用已經存在的OUTLINE,需要設置以下參數
Alter system/session set Query_rewrite_enabled = true
Alter system/session set use_stored_outlines = true

[Q]v $sysstat中的class分別代表什麼
[A]統計類別
1 代表事例活動
2 代表Redo buffer活動
4 代表鎖
8 代表數據緩衝活動
16 代表OS活動
32 代表並行活動
64 代表表訪問
128 代表調試信息

[Q]怎麼殺掉特定的數據庫會話
[A] Alter system kill session 'sid,serial#';
或者
alter system disconnect session 'sid,serial#' immediate;
在win上,還可以採用oracle提供的orakill殺掉一個線程(其實就是一個Oracle進程)
在Linux/Unix上,可以直接利用kill殺掉數據庫進程對應的OS進程

[Q]怎麼快速查找鎖與鎖等待
[A]數據庫的鎖是比較耗費資源的,非凡是發生鎖等待的時候,我們必須找到發生等待的鎖,有可能的話,殺掉該進程。
這個語句將查找到數據庫中所有的DML語句產生的鎖,還可以發現,任何DML語句其實產生了兩個鎖,一個是表鎖,一個是行鎖。
可以通過alter system kill session ‘sid,serial#’來殺掉會話
SELECT /*+ rule */ s.username,
decode(l.type,'TM','TABLE LOCK',
'TX','ROW LOCK',
NULL) LOCK_LEVEL,
o.owner,o.object_name,o.object_type,
s.sid,s.serial#,s.terminal,s.machine,s.program,s.osuser
FROM v $session s,v $lock l,dba_objects o
WHERE l.sid = s.sid
AND l.id1 = o.object_id(+)
AND s.username is NOT NULL
假如發生了鎖等待,我們可能更想知道是誰鎖了表而引起誰的等待
以下的語句可以查詢到誰鎖了表,而誰在等待。
SELECT /*+ rule */ lpad(' ',decode(l.xidusn ,0,3,0))||l.oracle_username User_name,
o.owner,o.object_name,o.object_type,s.sid,s.serial#
FROM v $locked_object l,dba_objects o,v $session s
WHERE l.object_id=o.object_id
AND l.session_id=s.sid
ORDER BY o.object_id,xidusn DESC
以上查詢結果是一個樹狀結構,假如有子節點,則表示有等待發生。假如想知道鎖用了哪個回滾段,還可以關聯到V $rollname,其中xidusn就是回滾段的USN

[Q] 如何有效的刪除一個大表(extent數很多的表)
[A] 一個有很多(100k)extent的表,假如只是簡單地用drop table的話,會很大量消耗CPU(Oracle要對fet $、uet $數據字典進行操作),可能會用上幾天的時間,較好的方法是分多次刪除extent,以減輕這種消耗:
1. truncate table big-table reuse storage;
2. alter table big-table deallocate unused keep 2000m ( 原來大小的n-1/n);
3. alter table big-table deallocate unused keep 1500m ;
....
4. drop table big-table;

[Q]如何收縮臨時數據文件的大小
[A]9i以下版本採用
ALTER DATABASE DATAFILE 'file name' RESIZE 100M類似的語句
9i以上版本採用
ALTER DATABASE TEMPFILE 'file name' RESIZE 100M
注重,臨時數據文件在使用時,一般不能收縮,除非關閉數據庫或斷開所有會話,停止對臨時數據文件的使用。

[Q]怎麼清理臨時段
[A]可以使用如下辦法
1、 使用如下語句查看一下認誰在用臨時段
SELECT username,sid,serial#,sql_address,machine,program,
tablespace,segtype, contents
FROM v $session se,v $sort_usage su
WHERE se.saddr=su.session_addr
2、 那些正在使用臨時段的進程
SQL>Alter system kill session 'sid,serial#';
3、把TEMP表空間回縮一下
SQL>Alter tablespace TEMP coalesce;
還可以使用診斷事件
1、 確定TEMP表空間的ts#
SQL> select ts#, name FROM v $tablespace;
TS# NAME
-----------------------
0 SYSYEM
1 RBS
2 USERS
3* TEMP
……
2、 執行清理操作
alter session set events 'immediate trace name DROP_SEGMENTS level TS#+1'
說明:
temp表空間的TS# 爲 3*, So TS#+ 1= 4
假如想清除所有表空間的臨時段,則
TS# = 2147483647

[Q]怎麼樣dump數據庫內部結構,如上面顯示的控制文件的結構
[A]常見的有
1、分析數據文件塊,轉儲數據文件n的塊m
alter system dump datafile n block m
2、分析日誌文件
alter system dump logfile logfilename;
3、分析控制文件的內容

alter session set events 'immediate trace name CONTROLF level 10'
4、分析所有數據文件頭
alter session set events 'immediate trace name FILE_HDRS level 10'
5、分析日誌文件頭
alter session set events 'immediate trace name REDOHDR level 10'
6、分析系統狀態,最好每10分鐘一次,做三次對比
alter session set events 'immediate trace name SYSTEMSTATE level 10'
7、分析進程狀態
alter session set events 'immediate trace name PROCESSSTATE level 10'
8、分析Library Cache的具體情況
alter session set events 'immediate trace name library_cache level 10'

[Q]如何獲得所有的事件代碼
[A] 事件代碼範圍一般從10000 to 10999,以下列出了這個範圍的事件代碼與信息
SET SERVEROUTPUT ON
DECLARE
err_msg VARCHAR2(120);
BEGIN
dbms_output.enable (1000000);
FOR err_num IN 10000..10999
LOOP
err_msg := SQLERRM (-err_num);
IF err_msg NOT LIKE '%Message '||err_num||' not found%' THEN
dbms_output.put_line (err_msg);
END IF;
END LOOP;
END;
/
在Unix系統上,事件信息放在一個文本文件裏
$ORACLE_HOME/rdbms/mesg/oraus.msg
可以用如下腳本查看事件信息
event=10000
while [ $event -ne 10999 ]
do
event=`expr $event + 1`
oerr ora $event
done
對於已經確保的/正在跟蹤的事件,可以用如下腳本獲得
SET SERVEROUTPUT ON
DECLARE
l_level NUMBER;
BEGIN
FOR l_event IN 10000..10999
LOOP
dbms_system.read_ev (l_event,l_level);
IF l_level > 0 THEN
dbms_output.put_line ('Event '||TO_CHAR (l_event)||
' is set at level '||TO_CHAR (l_level));
END IF;
END LOOP;
END;
/

[Q]什麼是STATSPACK,我怎麼使用它?
[A]Statspack是Oracle 8i以上提供的一個非常好的性能監控與診斷工具,基本上全部包含了BSTAT/ESTAT的功能,更多的信息
可以參考附帶文檔 $ORACLE_HOME/rdbms/admin/spdoc.txt。
安裝Statspack:
cd $ORACLE_HOME/rdbms/admin
sqlplus "/ as sysdba" @spdrop.sql -- 卸載,第一次可以不需要
sqlplus "/ as sysdba" @spcreate.sql -- 需要根據提示輸入表空間名
使用Statspack:
sqlplus perfstat/perfstat
exec statspack.snap; -- 進行信息收集統計,每次運行都將產生一個快照號
-- 獲得快照號,必須要有兩個以上的快照,才能生成報表
select SNAP_ID, SNAP_TIME from STATS $SNAPSHOT;
@spreport.sql -- 輸入需要查看的開始快照號與結束快照號
其他相關腳本s:
spauto.sql - 利用dbms_job提交一個作業,自動的進行STATPACK的信息收集統計
sppurge.sql - 清除一段範圍內的統計信息,需要提供開始快照與結束快照號
sptrunc.sql - 清除(truncate)所有統計信息

第五部分、ORACLE網絡與安全
[Q]如何限定特定IP訪問數據庫
[A]可以利用登錄觸發器、cmgw或者是在 $OREACLE_HOME/network/admin下新增一個protocol.ora文件(有些os可能是. protocol.ora),9i可以直接修改sqlnet.ora:
增加如下內容:
tcp.validnode_checking=yes
#答應訪問的ip
tcp.inited_nodes=(ip1,ip2,……)
#不答應訪問的ip
tcp.excluded_nodes=(ip1,ip2,……)

[Q]如何穿過防火牆連接數據庫
[A]這個問題只會在WIN平臺出現,UNIX平臺會自動解決。
解決方法:
服務器端的SQLNET.ORA應類似
SQLNET.AUTHENTICATION_SERVICES= (NTS)
NAMES.DIRECTORY_PATH= (TNSNAMES, ONAMES, HOSTNAME)
TRACE_LEVEL_CLIENT = 16
註冊表的HOME0加[HKEY_LOCAL_MACHINE]
USE_SHARED_SOCKET=TRUE

[Q]如何利用hostname方式連接數據庫
host name方式只支持tcp/ip協議的小局域網
修改listener.ora中的如下信息
(SID_DESC =
(GLOBAL_DBNAME = ur_hostname) --你的機器名

(ORACLE_HOME = E:oracleora92) --oracle home
(SID_NAME = orcl) --sid name
)
然後在客戶端
的sqlnet.ora中,確保有
NAMES.DIRECTORY_PATH= (HOSTNAME)
你就可以利用數據庫服務器的名稱訪問數據庫

[Q]dbms_repcat_admin能帶來什麼安全隱患
[A]假如一個用戶能執行dbms_repcat_admin包,將獲得極大的系統權限。
以下情況可能獲得該包的執行權限:
1、在sys下grant execute on dbms_repcat_admin to public[|user_name]
2、用戶擁有execute any procedure特權(僅限於9i以下,9i必須顯示授權)
假如用戶通過執行如下語句:
exec sys.dbms_repcat_admin.grant_admin_any_schema('user_name');
該用戶將獲得極大的系統特權
可以從user_sys_privs中獲得具體信息

[Q]在不知道用戶密碼的時候,怎麼樣跳轉到另外一個用戶執行操作後並不影響該用戶?
[A]我們通過如下的方法,可以安全使用該用戶,然後再跳轉回來,在某些時候比較有用
需要Alter user權限或DBA權限:
SQL> select password from dba_users where username='SCOTT';
PASSWORD
-----------------------------
F894844C34402B67
SQL> alter user scott identified by lion;
User altered.
SQL> connect scott/lion
Connected.
REM Do whatever you like...
SQL> connect system/manager
Connected.
SQL> alter user scott identified by values 'F894844C34402B67';
User altered.
SQL> connect scott/tiger
Connected.

[Q]如何加固你的數據庫
[A]要注重以下方面
1. 修改sys, system的口令。
2. Lock,修改,刪除默認用戶: dbsnmp,ctxsys等。
3. 把REMOTE_OS_AUTHENT改成False,防止遠程機器直接登陸。
4. 把O7_DICTIONARY_ACCESSIBILITY改成False。
5. 把一些權限從PUBLIC Role取消掉。
6. 檢查數據庫的數據文件的安全性。不要設置成666之類的。檢查其他dba 用戶。
7. 把一些不需要的服務(比如ftp, nfs等關閉掉)
8. 限制數據庫主機上面的用戶數量。
9. 定期檢查Metalink/OTN上面的security Alert。比如:http://otn.oracle.com/deploy/security/alerts.htm
10. 把你的數據庫與應用放在一個單獨的子網中,要不然你的用戶密碼很輕易被sniffer去。或者採用advance security,對用戶登錄加密。
11. 限止只有某些ip才能訪問你的數據庫
12. lsnrctl 要加密碼,要不然別人很輕易從外面關掉你的listener。
13. 假如可能,不要使用默認1521端口

[Q]如何檢查用戶是否用了默認密碼
[A]假如使用默認密碼,很可能就對你的數據庫造成一定的安全隱患,那麼可以使用如下的查詢獲得那些用戶使用默認密碼
select username "User(s) with Default Password!"
from dba_users
where password in
('E066D214D5421CCC', -- dbsnmp
'24ABAB8B06281B4C', -- ctxsys
'72979A94BAD2AF80', -- mdsys
'C252E8FA117AF049', -- odm
'A7A32CD03D3CE8D5', -- odm_mtr
'88A2B2C183431F00', -- ordplugins
'7EFA02EC7EA6B86F', -- ordsys
'4A3BA55E08595C81', -- outln
'F894844C34402B67', -- scott
'3F9FBD883D787341', -- wk_proxy
'79DF7A1BD138CF11', -- wk_sys
'7C9BA362F8314299', -- wmsys
'88D8364765FCE6AF', -- xdb
'F9DA8977092B7B81', -- tracesvr
'9300C0977D7DC75E', -- oas_public
'A97282CE3D94E29E', -- websys
'AC9700FD3F1410EB', -- lbacsys
'E7B5D92911C831E1', -- rman
'AC98877DE1297365', -- perfstat
'66F4EF5650C20355', -- exfsys
'84B8CBCA4D477FA3', -- si_informtn_schema
'D4C5016086B2DC6A', -- sys
'D4DF7931AB130E37') -- system
/

[Q]如何修改默認的XDB監聽端口
[A] Oracle9i默認的XML DB把HTTP的默認端口設爲8080,這是一個太常用的端口了,很多別的WebServer都會使用這個端口,
假如我們安裝了它,最好修改一下,避免衝突,假如不使用呢,就最好不要安裝
提供三種修改的方法
1.dbca,選擇你的數據庫,然後Standard Database Features->Customize->Oracle XML DB option,進入這個畫面你應該就知道怎麼改了。

2.OEM console,在XML Database 的配置裏面修改
3.用oracle提供的包:
-- 把HTTP/WEBDAV端口從8080改到8081
SQL> call dbms_xdb.cfg_update(updateXML(dbms_xdb.cfg_get(),
'/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()',8081))
/
-- 把FTP端口從2100改到2111
SQL> call dbms_xdb.cfg_update(updateXML(dbms_xdb.cfg_get(),
'/xdbconfig/sysconfig/protocolconfig/ftpconfig/ftp-port/text()',2111))
/
SQL> commit;
SQL> exec dbms_xdb.cfg_refresh;
-- 檢查修改是否已經成功
SQL> select dbms_xdb.cfg_get from dual;

[Q]怎麼捕捉用戶登錄信息,如SID,IP地址等
[A]可以利用登錄觸發器,如
CREATE OR REPLACE TRIGGER tr_login_record
AFTER logon ON DATABASE
DECLARE
miUserSid NUMBER;
mtSession v $session%ROWTYPE;
CURSOR cSession(iiUserSid IN NUMBER) IS
SELECT * FROM v $session
WHERE sid=iiUserSid;
BEGIN
SELECT sid INTO miUserSid FROM v $mystat WHERE rownum<=1;
OPEN cSession(miUserSid);
FETCH cSession INTO mtSession;
--if user exists then insert data
IF cSession%FOUND THEN
INSERT INTO log $information(login_user,login_time,ip_adress,ausid,terminal,
osuser,machine,program,sid,serial#)
VALUES(ora_login_user,SYSDATE,SYS_CONTEXT ('USERENV','IP_ADDRESS'),
userenv('SESSIONID'),
mtSession.Terminal,mtSession.Osuser,
mtSession.Machine,mtSession.Program,
mtSession.Sid,mtSession.Serial#);
ELSE
--if user don't exists then return error
sp_write_log('Session Information Error:'||SQLERRM);
CLOSE cSession;
raise_application_error(-20099,'Login Exception',FALSE);
END IF;
CLOSE cSession;
EXCEPTION
WHEN OTHERS THEN
sp_write_log('Login Trigger Error:'||SQLERRM);
END tr_login_record;
在以上觸發器中需要注重以下幾點
1、該用戶有v_ $session與v_ $mystat的對象查詢權限,可以在sys下對該擁護顯式授權。
2、sp_write_log原本是一個寫日誌的過程,可以置換爲自己的需要,如null跳過。
3、必須在創建該觸發器之前創建一個log $information的表記錄登錄信息。

[Q]怎麼捕捉整個數據庫的DDL語句或者是說對象結構變化與修改
[A]可以採用DDL觸發器,如
CREATE OR REPLACE TRIGGER tr_trace_ddl
AFTER DDL ON DATABASE
DECLARE
sql_text ora_name_list_t;
state_sql ddl $trace.ddl_sql%TYPE;
BEGIN
FOR i IN 1..ora_sql_txt(sql_text) LOOP
state_sql := state_sql||sql_text(i);
END LOOP;
INSERT INTO ddl $trace(login_user,ddl_time,ip_address,audsid,
schema_user,schema_object,ddl_sql)
VALUES(ora_login_user,SYSDATE,userenv('SESSIONID'),
sys_context('USERENV','IP_ADDRESS'),
ora_dict_obj_owner,ora_dict_obj_name,state_sql);
EXCEPTION
WHEN OTHERS THEN
sp_write_log('Capture DDL Excption:'||SQLERRM);
END tr_trace_ddl;
在創建以上觸發器時要注重幾點
1、必須創建一個ddl $trace的表,用來記錄ddl的記錄
2、sp_write_log原本是一個寫日誌的過程,可以置換爲自己的需要,如null跳過。

[Q]怎麼捕捉表上的DML語句(不包括select)語句)
[A]可以採用dml觸發器,如
CREATE OR REPLACE TRIGGER tr_capt_sql
BEFORE DELETE OR INSERT OR UPDATE
ON manager.test
DECLARE
sql_text ora_name_list_t;
state_sql capt $sql.sql_text%TYPE;
BEGIN
FOR i IN 1..ora_sql_txt(sql_text) LOOP
state_sql := state_sql || sql_text(i);
END LOOP;
INSERT INTO capt $sql(login_user,capt_time,ip_address,audsid,owner,table_name,sql_text)

VALUES(ora_login_user,sysdate,sys_context('USERENV','IP_ADDRESS'),
userenv('SESSIONID'),'MANAGER','TEST',state_sql);
EXCEPTION
WHEN OTHERS THEN
sp_write_log('Capture DML Exception:'||SQLERRM);
END tr_capt_sql;
在創建以上觸發器時要注重幾點
1、必須創建一個capt $sql的表,用來記錄ddl的記錄
2、sp_write_log原本是一個寫日誌的過程,可以置換爲自己的需要,如null跳過。

第六部分、OS相關與其它
[Q]怎麼樣生成日期格式的文件
[A]在LINUX/UNIX上,使用`date +%y%m%d` (`這個是鍵盤上~所在的那個鍵) 或 $(date +%y%m%d),如:
touch exp_table_name_`date +%y%m%d`.dmp
DATE= $(date +%y%m%d)
或者
DATE= $(date +%Y%m%d --date '1 days ago') #獲取昨天或多天前的日期
Windows上,使用%date:~4,10%,其中4是開始字符,10是提取長度,表示從date生成的日期中,提取從4開始長度是10的串。你可以改成其它你需要的數字,如:
Echo %date:~4,10%
假如想得到更精確的時間,win上面還可以使用time

[Q]測試磁盤與陣列性能
[A]用類似如下的方法測試寫能力
time dd if=/dev/zero f=/oradata/biddb/testind/testfile.dbf bs=1024000 count=1000
期間系統IO 使用可以用(unix):
iostat -xnp 2 顯示Busy程度

[Q]怎麼配置SSH密匙
[A]可以防止"中間人"的進攻方式
1、ssh-keygen 或ssh-keygen -d(ssh 2.x)生成鑰匙
2、然後拷貝公匙到你想登錄的服務器,改名爲authorized_keys,假如是3.0以下版本,需要改爲authorized_keys2
3、還可以利用config文件進一步簡化操作

Host *bj
HostName 機器名或IP
User 用戶名
有了這個配置文件,你就可以利用ssh bj來訪問指定的機器了,也就可以利用scp與sftp來傳送文件了。

[Q]FTP怎麼在腳本中自動上傳/下載
[A]可以把FTP寫到shell腳本中,如
ftp -n -i 主機IP &lt;&lt;EOF
user username pass
cd 目標目錄
put file
get file
#查詢文件
ls
#退出
bye
EOF&lt;/P&lt; p>

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