1、如果hosts文件中不含localhost,在启动listener是报错:
TNS-12537: TNS:connection closed
TNS-12560: TNS:protocol adapter error
TNS-00507: Connection closed
Linux Error: 29: Illegal seek
需要在 Listener文件中添加SUBSCRIBE_FOR_NODE_DOWN_EVENT_LISTENER=OFF,这个为oracle10g上的bug,有补丁可以解决
2、修改主机名步骤
第一步:
#hostname oratest
第二步:
修改/etc/sysconfig/network中的hostname
第三步:
修改/etc/hosts文件
3、listener中的ip地址不能为127.0.0.1/localhost(最好直接使用网卡ip地址),不然不能被该主机外的其他主机访问
4、修改主机名后,要在hosts文件中做对应修改,不然重启oracle后会报错:
ORA-00600: internal error code, arguments: [keltnfy-ldmInit], [46], [1], [], [], [], [], []
oracle表三种链接
Nested loop join
步骤:确定一个驱动表(outer table),另一个表为inner table,驱动表中的每一行与inner表中的相应记录JOIN。类似一个嵌套的循环。适用于驱动表的记录集比较小(<10000)而且inner表需要有有效的访问方法(Index)。需要注意的是:JOIN的顺序很重要,驱动表的记录集一定要小,返回结果集的响应时间是最快的。
[sql]
cost = outer access cost + (inner access cost * outer cardinality)
| 2 | NESTED LOOPS | | 3 | 141 | 7 (15)|
| 3 | TABLE ACCESS FULL | EMPLOYEES | 3 | 60 | 4 (25)|
| 4 | TABLE ACCESS BY INDEX ROWID| JOBS | 19 | 513 | 2 (50)|
| 5 | INDEX UNIQUE SCAN | JOB_ID_PK | 1 | | |
EMPLOYEES为outer table, JOBS为inner table.
[/sql]
Hash join
步骤:将两个表中较小的一个在内存中构造一个HASH表(对JOIN KEY),扫描另一个表,同样对JOIN KEY进行HASH后探测是否可以JOIN。适用于记录集比较大的情况。需要注意的是:如果HASH表太大,无法一次构造在内存中,则分成若干个partition,写入磁盘的temporary segment,则会多一个写的代价,会降低效率。
cost = (outer access cost * # of hash partitions) + inner access cost -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 665 | 13300 | 8 (25)| | 1 | HASH JOIN | | 665 | 13300 | 8 (25)| | 2 | TABLE ACCESS FULL | ORDERS | 105 | 840 | 4 (25)| | 3 | TABLE ACCESS FULL | ORDER_ITEMS | 665 | 7980 | 4 (25)| -------------------------------------------------------------------------- ORDERS为HASH TABLE,ORDER_ITEMS扫描
Sort merge join
步骤:将两个表排序,然后将两个表合并。通常情况下,只有在以下情况发生时,才会使用此种JOIN方式:
1.RBO模式
2.不等价关联(>,<,>=,<=,<>)
3.HASH_JOIN_ENABLED=false
4.数据源已排序
cost = (outer access cost * # of hash partitions) + inner access cost
Redhat 中裸设备(raw) 的配置和oracle中使用
1、对磁盘进行分区
fdisk -l 查看磁盘情况
fdisk /dev/sdb 进行分区操作
2、配置裸设备(修改/etc/udev/rules.d/60-raw.rules文件)
在redhat5中
1)加载裸设备
ACTION==”add”, KERNEL==”/dev/sdb1″,RUN+=”/bin/raw /dev/raw/raw1 %N”–多个一次累加
2)设置raw设备的用户和权限信息
ACTION==”add”, KERNEL==”raw[1-4]”, OWNER=”oracle”, GROUP=”dba”, MODE=”660″
3)重启服务
start_udev
4)查看raw设备
ls -lrt /dev/raw或者 raw -aq
在redhat4中
1)编辑/etc/sysconfig/rawdevices
vi /etc/sysconfig/rawdevices
/dev/raw/raw31 /dev/sdc5
/dev/raw/raw32 /dev/sdc6
/dev/raw/raw33 /dev/sdc7
/dev/raw/raw34 /dev/sdc8
2)执行绑定操作
/sbin/service rawdevices restart
3)设置权限
vi /etc/rc.local中添加
chown oracle:dba /dev/raw/raw31
chown oracle:dba /dev/raw/raw32
chown oracle:dba /dev/raw/raw33
chown oracle:dba /dev/raw/raw34
chmod 775 /dev/raw/raw31
chmod 775 /dev/raw/raw32
chmod 775 /dev/raw/raw33
chmod 775 /dev/raw/raw34
3、在oracle中使用
1)表空间
create tablespace raw1 datafile ‘/dev/raw/raw31’ size 450m;
2)联机日志
alter database add logfile group 4 (‘/dev/raw/raw32’) size 100m;
3)undo空间
create undo tablespace undo2 datafile ‘/dev/raw/raw33’ size 100m reuse;
4、注意事宜
1)一个裸设备只能放一个oracle文件
2)oracle文件大小要稍微小于裸设备大小
查询oracle被锁对象并解锁
1、查询oracle被锁对象及其语句
SELECT a_s.owner, a_s.object_name, a_s.object_type, VN.SID, VN.SERIAL#, VS.SPID "OS_PID", VN.PROCESS "CLIENT_PID", VN.USERNAME, VN.OSUSER, VN.MACHINE "HOSTNAME" , VN.TERMINAL, VN.PROGRAM, TO_CHAR(VN.LOGON_TIME,'YYYY-MM-DD HH24:MI:SS')"LOGIN_TIME", 'alter system kill session '''||vn.sid||','||vn.serial#||''';' "ORACKE_KILL", 'kill -9 '|| VS.SPID "OS_KILL" FROM ALL_OBJECTS A_S, V$LOCKED_OBJECT V_T, V$SESSION VN, V$PROCESS VS WHERE A_S.OBJECT_ID=V_T.OBJECT_ID AND V_T.SESSION_ID =VN.SID AND VS.ADDR=VN.PADDR AND VN.USERNAME NOT IN('SYSMAN','SYS');
2、查询该sid的sql语句
select * from v$sql vl,v$session vn where vl.ADDRESS= decode(vn.SQL_ADDRESS,null,vn.PREV_SQL_ADDR,VN.SQL_ADDRESS) and vn.sid=&sid;
3、解锁
alter system kill session 'sid,serial#'; --note:不能kill自身
4、查询被锁对象增强版
SELECT DDL.OWNER AS 用户, DDL.NAME AS 对象, DDL.type AS 类型, VS.OSUSER AS OS_USER, VS.MACHINE, VS.STATUS, VS.PROGRAM, VS.LOGON_TIME AS "LOGIN_TIME", VP.SPID, 'kill -9 ' || VP.SPID AS OS_KILL, vs.sid, vs.SERIAL#, 'alter system kill session ''' || vs.sid || ',' || vs.serial# || ''';' "ORACKE_KILL" FROM DBA_DDL_LOCKS DDL, V$SESSION VS, V$PROCESS VP WHERE DDL.SESSION_ID = VS.SID AND VS.PADDR = VP.ADDR;
oracle常用hint的用法
1. /*+ALL_ROWS*/
表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化.
2. /*+FIRST_ROWS*/
表明对语句块选择基于开销的优化方法,并获得最佳响应时间,使资源消耗最小化.
3. /*+CHOOSE*/
表明如果数据字典中有访问表的统计信息,将基于开销的优化方法,并获得最佳的吞吐量;
表明如果数据字典中没有访问表的统计信息,将基于规则开销的优化方法;
4. /*+RULE*/
表明对语句块选择基于规则的优化方法.
5. /*+FULL(TABLE)*/
表明对表选择全局扫描的方法.
6. /*+ROWID(TABLE)*/
提示明确表明对指定表根据ROWID进行访问.
7. /*+CLUSTER(TABLE)*/
提示明确表明对指定表选择簇扫描的访问方法,它只对簇对象有效.
8. /*+INDEX(TABLE INDEX_NAME)*/
表明对表选择索引的扫描方法.
9. /*+INDEX_ASC(TABLE INDEX_NAME)*/
表明对表选择索引升序的扫描方法.
10. /*+INDEX_COMBINE*/
为指定表选择位图访问路经,如果INDEX_COMBINE中没有提供作为参数的索引,将选择出位图索引的布尔组合方式.
11. /*+INDEX_JOIN(TABLE INDEX_NAME)*/
提示明确命令优化器使用索引作为访问路径.
12. /*+INDEX_DESC(TABLE INDEX_NAME)*/
表明对表选择索引降序的扫描方法.
13. /*+INDEX_FFS(TABLE INDEX_NAME)*/
对指定的表执行快速全索引扫描,而不是全表扫描的办法.
14. /*+ADD_EQUAL TABLE INDEX_NAM1,INDEX_NAM2,…*/
提示明确进行执行规划的选择,将几个单列索引的扫描合起来.
15. /*+USE_CONCAT*/
对查询中的WHERE后面的OR条件进行转换为UNION ALL的组合查询.
16. /*+NO_EXPAND*/
对于WHERE后面的OR 或者IN-LIST的查询语句,NO_EXPAND将阻止其基于优化器对其进行扩展.
17. /*+NOWRITE*/
禁止对查询块的查询重写操作.
18. /*+REWRITE*/
可以将视图作为参数.
19. /*+MERGE(TABLE)*/
能够对视图的各个查询进行相应的合并.
20. /*+NO_MERGE(TABLE)*/
对于有可合并的视图不再合并.
21. /*+ORDERED*/
根据表出现在FROM中的顺序,ORDERED使ORACLE依此顺序对其连接.
22. /*+USE_NL(TABLE)*/
将指定表与嵌套的连接的行源进行连接,并把指定表作为内部表.
23. /*+USE_MERGE(TABLE)*/
将指定的表与其他行源通过合并排序连接方式连接起来.
24. /*+USE_HASH(TABLE)*/
将指定的表与其他行源通过哈希连接方式连接起来.
25. /*+DRIVING_SITE(TABLE)*/
强制与ORACLE所选择的位置不同的表进行查询执行.
26. /*+LEADING(TABLE)*/
将指定的表作为连接次序中的首表.
27. /*+CACHE(TABLE)*/
当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端
28. /*+NOCACHE(TABLE)*/
当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端
29. /*+APPEND*/
直接插入到表的最后,可以提高速度.
30. /*+NOAPPEND*/
通过在插入语句生存期内停止并行模式来启动常规插入.
31. /*+ NO_INDEX ( table [index [index]…] ) */
指定不使用哪些索引
32. /*+ parallel(table,num)*/
指定表访问并发度
TKPROF使用
1、设置sql跟踪
--系统级别 alter system set sql_trace=true; alter system set sql_trace=false; --会话级别 alter session set sql_trace=true; alter session set sql_trace=false; --其他会话 exec sys.dbms_system.set_sql_trace_in_session(16737 , 39196 , true); exec sys.dbms_system.set_sql_trace_in_session(16737 , 39196 , false);
2、执行相关sql语句
需要跟踪的sql
3、查询trace 文件
select d.value||'/'||lower(rtrim(i.instance,chr(0)))||'_ora_'||p.spid||'.trc' trace_file_name from (select p.spid from v$mystat m, v$session s,v$process p where m.statistic# = 1 and s.sid = m.sid and p.addr = s.paddr ) p, (select t.instance from v$thread t,v$parameter v where v.name = 'thread' and(v.value = 0 or t.thread# = to_number(v.value))) i, (select value from v$parameter where name = 'user_dump_dest') d
4、使用TKPROF命令
tkprof trace_file_name out_file explain=username/password TKPROF DLSUN12_JANE_FG_SVRMGR_007.TRC OUTPUTA.PRF EXPLAIN=SCOTT/TIGER TABLE=SCOTT.TEMP_PLAN_TABLE_A INSERT=STOREA.SQL SYS=NO SORT=(EXECPU,FCHCPU)
5、排序选项说明
prscnt number of times parse was called
prscpu cpu time parsing
prsela elapsed time parsing
prsdsk number of disk reads during parse
prsqry number of buffers for consistent read during parse
prscu number of buffers for current read during parse
prsmis number of misses in library cache during parse
execnt number of execute was called
execpu cpu time spent executing
exeela elapsed time executing
exedsk number of disk reads during execute
exeqry number of buffers for consistent read during execute
execu number of buffers for current read during execute
exerow number of rows processed during execute
exemis number of library cache misses during execute
fchcnt number of times fetch was called
fchcpu cpu time spent fetching
fchela elapsed time fetching
fchdsk number of disk reads during fetch
fchqry number of buffers for consistent read during fetch
fchcu number of buffers for current read during fetch
fchrow number of rows fetched
userid userid of user that parsed the cursor
查找oracle所有表中的特定列中的数据
找出数据库中所有表表中REMARK列中含有WN、wind、wlr中表名和数量
declare i number:=0; begin for c1 in (select table_name from user_tab_columns where column_name='REMARK') loop EXECUTE IMMEDIATE 'select count(*) from '|| c1.table_name ||' where UPPER(REMARK) LIKE ''%WN%'' or UPPER(remark) like ''%WIND%'' or UPPER(remark) like ''%WLR%''' into i; if i>0 then dbms_output.put_line(c1.table_name||'------'||i); end if; end loop; end;
触发器实现指定用户登录oracle
1、创建允许登录用户表
CREATE TABLE "CHF"."LOG$LOGIN_OS" ( "OS_USER" VARCHAR2(60 BYTE) )
2、创建触发器实现限制用户登录
create or replace TRIGGER TR_LOGIN_RECORD_TEST AFTER logon ON DATABASE DECLARE mtSession v$session%ROWTYPE; CURSOR cSession(iiQuerySid IN NUMBER) IS SELECT * FROM v$session where USERNAME is not null and nvl(osuser,'x') <> 'SYSTEM' and type <> 'BACKGROUND' and audsid = iiQuerySid; USER_NUM NUMBER(5); V_SQL VARCHAR2(100); BEGIN OPEN cSession(userenv('SESSIONID')); FETCH cSession INTO mtSession; IF cSession%FOUND THEN select count(*) into USER_NUM FROM CHF.LOG$LOGIN_OS WHERE OS_USER=mtSession.Osuser; IF USER_NUM!=0 THEN V_SQL:=' alter system kill session '||''''||mtSession.Sid||','||mtSession.Serial#||''''; EXECUTE IMMEDIATE V_SQL; END IF; END IF; CLOSE cSession; EXCEPTION WHEN OTHERS THEN -- dbms_output.put_line('登记登录信息错误:'||SQLERRM); RAISE; END;
注:使用sysdba帐号创建触发器,因为在oracle中user不能kill掉自己的session,如果是用sysdba那么就可以kill掉其他的任何非自身的session
触发器记录用户登录信息
1、先需要建立一张表,用于存放登陆信息
create table LOG$INFORMATION ( USERNAME VARCHAR2(30), TERMINAL VARCHAR2(50), IPADRESS VARCHAR2(20), OSUSER VARCHAR2(30), MACHINE VARCHAR2(64), PROGRAM VARCHAR2(64), SID NUMBER, SERIAL# NUMBER, AUSID NUMBER, LOGINTIME DATE default sysdate, LOGout_TIME date )
2、创建触发器,记载登录信息
CREATE OR REPLACE TRIGGER TR_LOGIN_RECORD AFTER logon ON DATABASE DECLARE mtSession v$session%ROWTYPE; CURSOR cSession(iiQuerySid IN NUMBER) IS SELECT * FROM v$session WHERE nvl(osuser,'x') <> 'SYSTEM' and type <> 'BACKGROUND' and audsid = iiQuerySid; BEGIN OPEN cSession(userenv('SESSIONID')); FETCH cSession INTO mtSession; IF cSession%FOUND THEN INSERT INTO log$information(username,logintime,terminal,ipadress,osuser,machine, program,sid,serial#,ausid) VALUES(USER,SYSDATE,mtSession.Terminal, SYS_CONTEXT ('USERENV','IP_ADDRESS'),mtSession.Osuser, mtSession.Machine,mtSession.Program,mtSession.Sid,mtSession.Serial#,userenv('SESSIONID')); END IF; CLOSE cSession; EXCEPTION WHEN OTHERS THEN RAISE; END;
3、用户登出触发器,记录登出时间
create or replace trigger TR_LOGOFF_RECORD before LOGOFF ON DATABASE DECLARE mtSession v$session%ROWTYPE; CURSOR cSession(iiQuerySid IN NUMBER) IS SELECT * FROM v$session where nvl(osuser,'x') <> 'SYSTEM' and type <> 'BACKGROUND' and audsid = iiQuerySid; BEGIN OPEN cSession(userenv('SESSIONID')); FETCH cSession INTO mtSession; IF cSession%FOUND THEN UPDATE LOG$INFORMATION SET LOGOUT_TIME=SYSDATE WHERE sid=mtSession.Sid AND serial#=mtSession.Serial#; END IF; CLOSE cSession; EXCEPTION WHEN OTHERS THEN RAISE; END;
使用sqlplus生产批量plsql
要点
chr(10)–表示换行
set heading off–不显示表格头部
set pagesize 0–不分页
set linesize 800–行宽
spool filename–写入到文件中
sql语句
select 'declare'||chr(10)||' i integer:=0;'||chr(10)||'cursor cur is select rowid as rid from '||t1 ||' WHERE DATASOURCE=''WN'' OR MODIFYSOURCE=''WN'';'||chr(10)||'begin for c in cur loop '||chr(10)||'i:=i+1;'||chr(10)|| 'update '||t1||chr(10)||'SET DATASOURCE=F_BYF_UPDATE_WN(datasource),MODIFYSOURCE=F_BYF_UPDATE_WN(MODIFYSOURCE),REMARK=F_BYF_UPDATE_WN(REMARK) WHERE rowid=c.rid;'||chr(10)|| ' if mod(i,200)=0 then'||chr(10)|| ' commit;'||chr(10)||'end if;'||chr(10)||' if mod(i,20000)=0 then'||chr(10)||' dbms_lock.sleep(40);'||chr(10)||' if i>30000 then'||chr(10)|| ' dbms_lock.sleep(40);'||chr(10)||' end if;'||chr(10)||' end if;'||chr(10)|| ' if i>500000 then'||chr(10)||' exit;'||chr(10)||' end if;'||chr(10)||' end loop;'||chr(10)||' commit;'||chr(10)||'end;'||chr(10)||'/'||chr(10)||'--------'||t1||'-------------' from t1;
效果
declare i integer:=0; cursor cur is select rowid as rid from FUND294 WHERE DATASOURCE='WN' OR MODIFYSOURCE='WN'; begin for c in cur loop i:=i+1; update FUND294 SET DATASOURCE=F_BYF_UPDATE_WN(datasource),MODIFYSOURCE=F_BYF_UPDATE_WN(MODIFYSOURCE),REMARK=F_BYF_UPDATE_WN(REMARK) WHERE rowid=c.rid; if mod(i,200)=0 then commit; end if; if mod(i,20000)=0 then dbms_lock.sleep(40); if i>30000 then dbms_lock.sleep(40); end if; end if; if i>500000 then exit; end if; end loop; commit; end; / --------FUND294-------------