Oracle进程管理
Oracle进程--server processes + 后台进程
---------------- --------
PGA SGA
server processes--功能:负责SQL语句的执行,包括从LRU链表中查找需要的数据块,将修改的内容写入缓冲区。
后台进程------功能:将缓冲区的内容写入磁盘:1、将log buffer中内容写入redo log文件, 2、将db buffer中的内容写入数据文件
3、生成检查点 4、监控系统和进程,发生故障的时候负责修复(自动)
1、进程参数
SQL> show parameter processes --模糊查询,带processes的参数都会被显示出来
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
processes integer 300 --当前实例允许的最大进程访问数为300
调整的最大额度必须在硬件承受的范围之内。
调到最大限度以后如果访问数量继续增加:需要 1、换设备 2、做集群
实例1 实例2 实例3 。。。 实例n
| | | |
-------------------------------------
|
数据库:数据文件(共享存储)
SQL> alter system set processes=350 scope=spfile;
System altered.
SQL> startup force
ORACLE instance started.
Total System Global Area 1258291200 bytes
Fixed Size 1267260 bytes
Variable Size 301992388 bytes
Database Buffers 922746880 bytes
Redo Buffers 32284672 bytes
Database mounted.
Database opened.
SQL> show parameter processes
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
processes integer 350
OS的内核参数中kernel.sem的第一段表示每个信号集合的最大数量,oralce实例承受的最大进程数。
kernel.sem = 250 32000 100 128
此时增大为350,但是这个内核参数没有调整是不起作用的,kernel.sem = 500 64000 100 128
除此之外,/etc/security/limits.conf 这个文件要修改
-------------------------------------------------------
* hard nproc 64000
--------------------------------------------------------
2、会话参数
专有服务器模式:一个进程默认启动一个session,原理上讲是一对一的关系。
session--从连接oracle开始到退出oracle,称为一个session。
SQL> show parameter sessions
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
sessions integer 390
实际上sessions要多一点。一个processes默认启动一个session,但是这个进程还会引发一些系统会话辅助,解析SQL,查询数据字典。
sessions/processes = 1.1~1.2
SQL> alter system set processes=400 scope=spfile;
System altered.
SQL> startup force
ORACLE instance started.
Total System Global Area 1258291200 bytes
Fixed Size 1267260 bytes
Variable Size 301992388 bytes
Database Buffers 922746880 bytes
Redo Buffers 32284672 bytes
Database mounted.
Database opened.
SQL> show parameter processes
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
processes integer 400
SQL> show parameter sessions
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
sessions integer 445
shared_server_sessions integer
sessions这个参数是不需要调整的,它会跟着processes的变化而变化的。
3、后台进程--无法人为干预,是Oracle系统本身自己控制的进程
[[email protected] ~]$ ps -ef|grep ora_
oracle 3544 1 0 15:41 ? 00:00:00 ora_pmon_ORCL --进程监控进程
oracle 3546 1 0 15:41 ? 00:00:00 ora_psp0_ORCL
oracle 3548 1 0 15:41 ? 00:00:00 ora_mman_ORCL
oracle 3550 1 0 15:41 ? 00:00:00 ora_dbw0_ORCL --数据文件写进程
oracle 3552 1 0 15:41 ? 00:00:00 ora_lgwr_ORCL --日志文件写进程,日志文件写入是不能并行的
oracle 3554 1 0 15:41 ? 00:00:00 ora_ckpt_ORCL ==检查点进程,将check point写入到控制文件、redo文件、数据文件头部
oracle 3556 1 0 15:41 ? 00:00:00 ora_smon_ORCL --系统监控进程
oracle 3558 1 0 15:41 ? 00:00:00 ora_reco_ORCL
oracle 3560 1 0 15:41 ? 00:00:00 ora_cjq0_ORCL
oracle 3562 1 0 15:41 ? 00:00:00 ora_mmon_ORCL
oracle 3564 1 0 15:41 ? 00:00:00 ora_mmnl_ORCL
oracle 3566 1 0 15:41 ? 00:00:00 ora_d000_ORCL
oracle 3568 1 0 15:41 ? 00:00:00 ora_s000_ORCL
oracle 3572 1 0 15:41 ? 00:00:00 ora_qmnc_ORCL
oracle 3578 1 0 15:41 ? 00:00:00 ora_j000_ORCL
oracle 3580 1 0 15:41 ? 00:00:00 ora_q000_ORCL
oracle 3582 1 0 15:41 ? 00:00:00 ora_q001_ORCL
[[email protected] ORCL]$ ll *.dbf
-rw-r----- 1 oracle oinstall 104865792 06-24 15:41 example01.dbf
-rw-r----- 1 oracle oinstall 1073750016 06-24 15:41 plsql01.dbf
-rw-r----- 1 oracle oinstall 356524032 06-24 15:41 sysaux01.dbf
-rw-r----- 1 oracle oinstall 545267712 06-24 15:41 system01.dbf
-rw-r----- 1 oracle oinstall 31465472 06-17 00:00 temp01.dbf
-rw-r----- 1 oracle oinstall 560996352 06-24 15:41 undotbs01.dbf
-rw-r----- 1 oracle oinstall 6561792 06-24 15:41 users01.dbf --就是DBWn进程将内容从db buffer cache写入的
[[email protected] ORCL]$ ll *.log
-rw-r----- 1 oracle oinstall 52429312 06-24 15:41 redo01.log
-rw-r----- 1 oracle oinstall 52429312 06-24 15:41 redo02.log
-rw-r----- 1 oracle oinstall 52429312 06-24 15:44 redo03.log --就是LGWR将log buffer中的内容写入到日志文件
###########################################################################################
实操案例:增加后台进程个数(DBWn)
SQL> show parameter db_writer
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_writer_processes integer 1
增加到4个
SQL> alter system set db_writer_processes=4 scope=spfile;
System altered.
SQL> startup force
ORACLE instance started.
Total System Global Area 1258291200 bytes
Fixed Size 1267260 bytes
Variable Size 301992388 bytes
Database Buffers 922746880 bytes
Redo Buffers 32284672 bytes
Database mounted.
Database opened.
[[email protected] ORCL]$ ps -ef|grep ora_dbw
oracle 3625 1 0 15:48 ? 00:00:00 ora_dbw0_ORCL
oracle 3627 1 0 15:48 ? 00:00:00 ora_dbw1_ORCL
oracle 3629 1 0 15:48 ? 00:00:00 ora_dbw2_ORCL
oracle 3631 1 0 15:48 ? 00:00:00 ora_dbw3_ORCL --DBWn进程
这个进程受CPU数量的影响,不是设置多少都能起作用的,这个进程和CPU的核数有关
现在调了4个,其实有三个是没用的,这个参数必须和核数是一致的。
SQL> show parameter cpu_count
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
cpu_count integer 1 --根据硬件情况自动感知的,表示CPU内核总数
SQL> show parameter threads
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
parallel_threads_per_cpu integer 2 --每个内核支持多线程最多2个
##########################################################################################
DBWn进程原理:
1、DB writer = DBWn 数据文件写进程
A 所有系统和数据库在读写数据文件的时候一定要先将数据块加载到内存,在内存中修改或者读取。
B DBWn将db buffer cache区域的已经被修改的数据块写入到数据文件
-----------------------------dirty block list---------------=================-------DBWn 写入==========数据文件
| ckpt2 ckpt1
| server processes将脏块移动到脏块链表上
-----------------------------LRU链表
|
| 修改:将修改过的数据块标示为dirty
server processes
脏数据--已经被修改了还没有写入数据文件的数据块。和commit无关。
由于IO异步方式,所以修改的块没有那么快被写入磁盘。异步IO方式性能更高。
已经提交的数据一定会被写到磁盘么?不一定。没有提交的数据一定不会被写入磁盘么?不一定,没有提交的数据也会被写到磁盘的,如果内存不足的话。
如果没有提交的数据被写入磁盘了,此时你需要回滚,那么oracle会用UNDO中的旧的镜像区覆盖磁盘,这个叫做磁盘上回滚。速度慢于在内存上回滚。所以在执行了大的事务后,回滚速度是很慢的。
DBWn是一批一批的方式写入磁盘的,当buffer cache空间被争用发现不足的时候,DBWN会启动将脏块写入磁盘,将内存空间释放出来。每写入一个批次,就在数据文件的头部写一个数字,checkpoint_change#(v$datafile_header),理解为数据文件的基线。实例恢复的起点。
###########################################################################################
2、LGWR--日志文件写进程
工作原理--将log buffer区域的日志条目写到redo文件,这个写操作几乎是同步的。
在以下几种条件下,LGWR会启动工作:
A 当用户提交一个事务的时候
B 每隔3s钟
C 日志缓冲区1/3满
D 切换日志文件
E 当修改数据量达到1M的时候
F 当DBWn进程将修改的数据(脏数据)写入磁盘的时候
启动频繁的目的就是为了尽快的将log buffer的内容的写入磁盘。保证日志写入是同步的。快速提交机制。
###########################################################################################
3、CKPT进程
系统更改号=SCN=system change number -- Oracle的时钟,每3S钟加1
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
2734726
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
2734729
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
2734730
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
2734731
checkpoint_change#--用SCN表示的一个基线(检查点事件)。checkpoint_change#永远小于当前的SCN的。
检查点:用SCN来表示的一个事件,这个事件叫检查点事件,这个事件由CKPT后台进程引发。
DBWn是一批一批的方式写入磁盘的,一个批次的脏块对应的就是两个检查点。当发生检查点事件的时候,DBWn会开始工作。
检查点和SCN是没有关系的,检查点仅仅是用SCN来表示的。
redo文件在数据库中是一组一组轮换使用的,那个文件的status是current表示当前LGWR进程正在写入这个文件。
SQL> alter system switch logfile;
System altered.
SQL> alter system switch logfile;
System altered.
SQL> alter system switch logfile;
System altered. --切换日志文件的时候一定会建立检查点事件!
-----------|-----|-----dirty list
ckpt2 ckpt1
由于此刻脏块不够多,并不会引发DBWn开始写入数据文件。等到脏块足够多的时候才会将其写入数据文件。
status--CURRENT--当前LGWR进程正在写入这个文件
INACTIVE--这个日志文件对应的脏块已经被写入磁盘,恢复实例的时候不再被用
ACTIVE--这个日志文件对应的脏块还没有被写入磁盘,恢复实例的时候被用
强制生成检查点并强制写入数据文件
SQL> alter system checkpoint;
System altered.
------|-----|-----|-----dirty list
CKPT3 ckpt2 ckpt1
此时将CKPT3之前的脏块全部写入磁盘,并将ckpt3写入数据文件头部。
2735299=ckpt3
当redo中没有INACTIVE的文件时候,切换就必须依靠DBWn进程将脏块写入磁盘,DBWn进程有让在线redo日志往前推的作用。 --redo文件有三个,DBWn脏块写入磁盘会切换redo文件,往前推表示往前切换。
在报警日志中看到相关的信息:
[[email protected] bdump]$ pwd
/u01/oracle/admin/ORCL/bdump
[[email protected] bdump]$ ll alert_ORCL.log
-rw-r----- 1 oracle oinstall 273927 06-26 14:48 alert_ORCL.log
Thu Jun 26 14:36:20 2014
Thread 1 advanced to log sequence 138 (LGWR switch)
Current log# 2 seq# 138 mem# 0: /u01/oracle/oradata/ORCL/redo02.log
Thu Jun 26 14:44:34 2014
Thread 1 advanced to log sequence 139 (LGWR switch)
Current log# 3 seq# 139 mem# 0: /u01/oracle/oradata/ORCL/redo03.log
Thu Jun 26 14:46:09 2014
Thread 1 advanced to log sequence 140 (LGWR switch)
Current log# 1 seq# 140 mem# 0: /u01/oracle/oradata/ORCL/redo01.log
Thu Jun 26 14:47:14 2014
Thread 1 cannot allocate new log, sequence 141 --redo还在被占用
Checkpoint not complete --检查点未完成的消息
Current log# 1 seq# 140 mem# 0: /u01/oracle/oradata/ORCL/redo01.log
Thu Jun 26 14:47:17 2014
Thread 1 advanced to log sequence 141 (LGWR switch)
Current log# 2 seq# 141 mem# 0: /u01/oracle/oradata/ORCL/redo02.log --切换成功
------------------------------------------------------------------------------------------------------------------
redo中的日志条目
SCN1 checkpoint RBA(redo block address) 1
SCN1 checkpoint RBA(redo block address) 2
SCN1 checkpoint RBA(redo block address) 3 检查点SCN就是checkpoint_change#,RBA是不会反应在视图上的
检查点参数:
SQL> show parameter log_check
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
log_checkpoint_interval integer 0 --这个参数在Oracle 10g下是废弃的
log_checkpoint_timeout integer 1800 --两次检查点之间的时间间隔。
log_checkpoints_to_alert boolean FALSE --将检查点信息写入报警日志文件
SQL> alter system set log_checkpoints_to_alert=true scope=both;
System altered.
SQL> alter system switch logfile;
System altered.
SQL> alter system switch logfile;
System altered.
SQL> alter system switch logfile;
System altered.
Thu Jun 26 15:29:18 2014
Beginning log switch checkpoint up to RBA [0x8f.2.10], SCN: 2736918 --日志143处检查点建立
Thu Jun 26 15:29:18 2014
Thread 1 advanced to log sequence 143 (LGWR switch)
Current log# 1 seq# 143 mem# 0: /u01/oracle/oradata/ORCL/redo01.log
Beginning log switch checkpoint up to RBA [0x90.2.10], SCN: 2736920
Thu Jun 26 15:29:19 2014
Thread 1 advanced to log sequence 144 (LGWR switch)
Current log# 2 seq# 144 mem# 0: /u01/oracle/oradata/ORCL/redo02.log
Thread 1 cannot allocate new log, sequence 145 --切换145
Checkpoint not complete
Current log# 2 seq# 144 mem# 0: /u01/oracle/oradata/ORCL/redo02.log
Thu Jun 26 15:29:22 2014
Completed checkpoint up to RBA [0x8f.2.10], SCN: 2736918 --日志143处检查点完成
Thu Jun 26 15:29:22 2014
Beginning log switch checkpoint up to RBA [0x91.2.10], SCN: 2736944 --切换到145对应的检查点
Thu Jun 26 15:29:22 2014
Thread 1 advanced to log sequence 145 (LGWR switch)
Current log# 3 seq# 145 mem# 0: /u01/oracle/oradata/ORCL/redo03.log
RBA [0x8f.2.10]
0x8f=143 表示的是日志的序号
2--日志文件块号
10--偏移量
redo文件中log buufer中的内容都是以日志条目的方式存储的:RBA [0x8f.2.10] SCN +具体内容
SQL> alter system dump logfile ‘/u01/oracle/oradata/ORCL/redo01.log‘;
System altered. --dump出redo文件,dump的内容是被存储在udump下的跟踪文件中的。
下面是一个典型的redo条目
REDO RECORD - Thread:1 RBA: 0x000090.00000057.00d0 LEN: 0x00b4 VLD: 0x02
SCN: 0x0000.0029c32d SUBSCN: 1 06/26/2014 15:29:22
CHANGE #1 MEDIA RECOVERY MARKER SCN:0x0000.00000000 SEQ: 0 OP:23.1
Block Written - afn: 14 rdba: 0x03800bf0 BFT:(1024,58723312) non-BFT:(14,3056)
scn: 0x0000.0029c323 seq: 0x03 flg:0x04
Block Written - afn: 14 rdba: 0x03800bf1 BFT:(1024,58723313) non-BFT:(14,3057)
scn: 0x0000.0029c323 seq: 0x03 flg:0x04
Block Written - afn: 14 rdba: 0x038006d3 BFT:(1024,58722003) non-BFT:(14,1747)
scn: 0x0000.0029c32a seq: 0x02 flg:0x04
Block Written - afn: 14 rdba: 0x03800079 BFT:(1024,58720377) non-BFT:(14,121)
scn: 0x0000.0029c32a seq: 0x02 flg:0x04
Block Written - afn: 14 rdba: 0x03800039 BFT:(1024,58720313) non-BFT:(14,57)
scn: 0x0000.0029c323 seq: 0x03 flg:0x04
Block Written - afn: 14 rdba: 0x03800019 BFT:(1024,58720281) non-BFT:(14,25)
scn: 0x0000.0029c32c seq: 0x02 flg:0x04
Block Written - afn: 3 rdba: 0x00c076e6 BFT:(1024,12613350) non-BFT:(3,30438)
scn: 0x0000.0029c32b seq: 0x02 flg:0x06
Block Written - afn: 3 rdba: 0x00c00a68 BFT:(1024,12585576) non-BFT:(3,2664)
scn: 0x0000.0029c2e9 seq: 0x01 flg:0x06
REDO RECORD - Thread:1 RBA: 0x000090.00000057.0184 LEN: 0x0104 VLD: 0x02
###########################################################################################
4 PMON进程--进程监控进程
作用:1、负责异常终止连接后完成清理。
2、负责监控其他的Orale后台进程,在必要的时候会重启这些进程
3、向Oracle TNS监听器注册实例
###########################################################################################
5、SMON进程--系统监控进程
作用:负责实例的恢复:清理不再使用的临时段、合并空闲空间、收缩回滚段
###########################################################################################
查杀有问题的进程
场景1:一个SQL开始执行之后,通过客户端没办法停止,必须找有DBA权限的用户去查找并且杀掉。(已知SQL)
场景2:系统由于某些耗性能的SQL语句太多导致IO太大,物理资源耗尽,需要把这个SQL语句找到杀掉。(未知SQL)
场景1的处理方法:
相关的视图:
SELECT * FROM v$session --当前系统启动后保留在内存中的所有的会话信息,一行是一个session,session可能正在执行,但是也可能执行完了。
SELECT * FROM v$session_wait --当前系统中正在执行的session,说明正在等待执行完。
SELECT * FROM v$sqltext --当前系统启动后保留在内存中的所有的执行过或者正在执行的SQL语句的信息
SELECT * FROM v$sqltext where sql_id=‘3ymrngv9f400q‘ order by piece
--一行是一个SQL的片段,需要经过sql id过滤后进行排序才能得到完整结果。
select a.*,b.sql_text from v$session a,v$sqltext b where a.SQL_ADDRESS = b.ADDRESS
引发一个消耗IO的SQL
SQL> select count(1) from testa,testb;
select a.*,b.sql_text from v$session a,v$sqltext b where a.SQL_ADDRESS = b.ADDRESS
通过上面视图查出sid=412 serial#=428
SQL> conn /as sysdba
Connected.
SQL> alter system kill session ‘412,428‘; --在数据库层面杀进程
System altered.
SQL> select count(1) from testa,testb;
select count(1) from testa,testb
*
ERROR at line 1:
ORA-00028: your session has been killed
上面已经杀掉进程,但是有时候我们是杀不掉的,我们需要到Linux操作系统层面去杀进程,方法如下:
在操作系统层面杀进程
查出对应的进程号
select a.*, b.sql_text, c.pid, c.spid
from v$session a, v$sqltext b, v$process c
where a.SQL_ADDRESS = b.ADDRESS
and a.PADDR = c.ADDR
spid--OS对这个进程的编号 8041
pid--ORACLE对这个进程的编号 26
[[email protected] ~]# kill -9 8041 --在操作系统层面杀进程
SQL> select count(1) from testa,testb;
select count(1) from testa,testb
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel --已经杀掉
###########################################################################################
场景2:我们需要找到出问题的SQL (内存IO耗光,硬盘IO耗光,CPU耗光)
Oracle缓存的命中率:每次查询数据块的时候都能在内存上找到,内存命中率就会高。性能好。内存命中率低,性能就会比较差,磁盘IO消耗就会很大。
找有问题的SQL语句一半以上是由于磁盘IO消耗引起的。
Oracle读操作不一定只用select操作才会引起的,update,insert,delete一样需要读操作。
Oracle读的模式--
1、根据物理位置分类:物理读和逻辑读
2、根据读的类型分类:当前读和一致性读
当前读--为了修改,保证读到的数据块是当前状态最新的(因为要修改,读取的时候别的进程不能正在修改),必须有修改数据操作才会有当前读,select语句是没有当前读的。如果加锁,不会去UNDO上读取。等待。不会发生读操作。
UNDO机制,回滚段,当DML开始的时候,数据的旧的镜像会被复制到UNDO表空间(disk上),在commit之前,如果有其他的进程要读取这个数据块的时候,在内存上发现这个正在被修改,但是无法修改,此时数据加锁了。就要等待。
一致性读--纯读,为了保证数据一致性而引发的读,select从UNDO或者内存上读取到的数据块块次,DML操作读取的,不需要修改的数据块块次统计(比如数据字典查询、索引的查询)。
统计单位:块次。
DML操作 select操作 读取位置
-------------------------------------------------------------------
当前读 Y N 可能是磁盘,也可能是内存
一致性读 Y Y 可能是磁盘,也可能是内存
--------------------------------------------------------------------------
dml操作--读取x个要修改的块,读取y个不修改的块,x就是当前读的块,y就是一致性读的块
seletc操作--读取内存中的块+磁盘上的块+UNDO上的块 都是一致性读
单位:块次。
当前读
SQL> col name format a30
SQL> select * from v$sysstat where name in(‘db block gets‘,‘db block gets direct‘,‘db block gets from cache‘);
STATISTIC# NAME CLASS VALUE STAT_ID
---------- ------------------------------ ---------- ---------- ----------
47 db block gets 8 1660925 1480709069
48 db block gets from cache 8 1656869 4017839461
49 db block gets direct 8 4056 95128520
db block gets = db block gets from cache + db block gets direct
一致性读
SQL> select * from v$sysstat where name in(‘consistent gets‘,‘consistent gets direct‘,‘consistent gets from cache‘);
STATISTIC# NAME CLASS VALUE STAT_ID
---------- ------------------------------ ---------- ---------- ----------
50 consistent gets 8 6452451 4162191256
51 consistent gets from cache 8 6452292 2839918855
53 consistent gets direct 8 159 420374750
consistent gets = consistent gets from cache + consistent gets direct
物理读(物理读即是把数据从磁盘读入到buffer catch的过程)
SQL> select * from v$sysstat where name in(‘physical reads‘);
STATISTIC# NAME CLASS VALUE STAT_ID
---------- ------------------------------ ---------- ---------- ----------
54 physical reads 8 30781 2263124246
缓存命中率= 1-物理读/全部读
缓存命中率= 1-physical reads/(db block gets + consistent gets)=1-30781/(6452451+1660925)
SQL> select 1-30781/(6452451+1660925) from dual;
1-30781/(6452451+1660925)
-------------------------
.996206142
根据经验:数据库的内存命中率在90%以上都是正常的。
找性能低下的SQL就是找命中率低于90%的SQL语句。
语句1
select a.EXECUTIONS,
a.DISK_READS,
a.SQL_ID,
a.BUFFER_GETS,
round((a.BUFFER_GETS - a.DISK_READS) / a.BUFFER_GETS, 2) hit_radio,
round(a.DISK_READS / a.EXECUTIONS, 2) reads_per_run
from v$sqlarea a
where a.EXECUTIONS > 0
and round((a.BUFFER_GETS - a.DISK_READS) / a.BUFFER_GETS, 2) < 0.9
and a.BUFFER_GETS > 0
order by a.sql_id
语句2
select a.*, b.sql_text
from v$session a, v$sqltext b
where a.SQL_ADDRESS = b.ADDRESS
and a.sql_id in
(select x.sql_id
from v$sqlarea x
where x.EXECUTIONS > 0
and round((x.BUFFER_GETS - x.DISK_READS) / x.BUFFER_GETS, 2) < 0.9
and x.BUFFER_GETS > 0) --查询有问题的SQL 查到sql_id之后再去语句1中查询具体的值
如下案例:
select a.EXECUTIONS,
a.DISK_READS,
a.SQL_ID,
a.BUFFER_GETS,
round((a.BUFFER_GETS - a.DISK_READS) / a.BUFFER_GETS, 2) hit_radio,
round(a.DISK_READS / a.EXECUTIONS, 2) reads_per_run
from v$sqlarea a
where a.EXECUTIONS > 0
and round((a.BUFFER_GETS - a.DISK_READS) / a.BUFFER_GETS, 2) < 0.9
and a.BUFFER_GETS > 0 and a.sql_id=‘cj6vhxvhvzkak‘
再查杀。
###########################################################################################