Buffer Cache
作用:缓存dbf中的数据
例子:A和B重复访问同一张表的几率是很大的,如果每次访问dbf时都要发生物理IO,这样会导致数据库的性能非常低
由于这个例子,当一个进程访问dbf时,Server Process首先会去buffer cache找表中的数据,如果数据存在,直接从Buffer cache中读取返回客户端,反之,如果数据不存在,则会从dbf中找,从dbf中将数据取出来放入buffer cache,然后在从buffer cache中进行读取。
重点:Server Process读取数据时,先去寻找的是Buffer cache
逻辑IO与物理IO
逻辑IO---逻辑读:Server Process直接从buffer cache读取数据(内存读)
物理IO---物理读:Server Process从磁盘上读取数据 (磁盘读)
逻辑读大于物理读,进而可以提高数据库的读速度
命中率
L/L+P 逻辑读/逻辑读+物理读
命中率高:逻辑读多,物理读少---较好
命中率低:逻辑读少,物理读多
命中率低,数据库一定有问题,但是命中率高也不一定没有问题
例子:假设L=90000 P=10000 那么命中率=90000/90000+10000,这里的L与P都很高,但是P高导致服务器性能变慢,所以命中率高也不一定好
总之需要综合命中率与物理读两项来判断好与坏
Server Process
Server Process修改某个数据的时候,首先将表中所需要的数据读入buffer cache,Server Process在内存中对表进行修改,在修改的时候会产生日志,而日志会写进redolog buffer中,此时内存中的数据与dbf中的数据是不一样的。
Server Process主要负责读出数据到内存,在内存中修改数据,将产生的日志写到Redolog buffer中,并不负责将修改后的数据写回磁盘,也不负责将日志写回磁盘
SQL语句执行流程
SQL--->Server Process--->解析--->执行计划--->取数据
后台进程
后台进程的特点:用户无感知
注意:数据库的优化重点在于Server Process,因为Server Process反应速度将代表数据库的运行速度
不管后台进程有多忙,只要serverprocess快速轻松,用户就会感到快速轻松,用户就会感到数据库很快,可能这时后台进程非常的繁忙,这是我们理想的一个结果。
(1)DBWn---将内存中的数据写回dbf(磁盘)
(2)LGWR---将redolog buffer中的日志写到日志文件中
(3)检查点进程---周期性的进行,把数据库的状态信息写到控制文件中和数据文件的头部,每一个数据文件的头部都会记录数据文件的状态信息
(4)SMON---主内,对数据库实例进行维护,对shared pool中的碎片进行整合,负责对数据库实例内部进行清理和维护,(系统监视器),对SGA的内部进行一个维护
举一个例子
共享池里面放的sql语句和执行计划
用的时间长了,里面可能出现很多碎片。
这时SMonitor会对这些碎片进行整合。
也就是说SMonitor负责对数据库实例内部进行清理和维护的
(5)PMON---主外,对Server Process进行维护和清理,清理无用的Server Process(进程监视器)
例子
客户网络突然断了,serverprocess还一直为用户启着。
PMonitor会周期性的启动,
启动后发现某个serverprocess它所对应的客户已经死掉了,
他会把这个serverprocess进行清理。
包括把这个serverprocess进程关掉,
把这个serverprocess所对应的PGA内存空间,给它清理。
(6)ARCn归档日志进程
oracle中有很多日志文件,但是oracle最多只能保持三组日志,oracle首先使用第一组日志,往里记日志,等到第一个日志记完时,再往第二个日志文件中记录,第二组记满,使用第三组,而当第三组满了,反过来使用第一组。这时就把第一组覆盖了。
因为oracle最多只能保留三组日志,为了可以保留更多的日志,oracle有一个归档的工作模式。
写第一组日志,写满了这时候
oracle会启动一个进程叫ARCn。
这个进程会把日志归档到另外一个目录底下去,另外起一个名字,
大小和它一样。
然后开始写第二个日志log文件,第二个写满切到第三个的时候,
这个进程把第二个log日志写到归档到的那个目录下。
然后写第三个、第四个。
在归档这个位置,
保留了oracle所有的日志
我们要找较早的数据较早的日志会从归档中找。
Buffer Cache数据块
可以分为四种:
(1)干净:内存与磁盘的数据一致
(2)脏数据:内存与磁盘的数据不一致
(3)空闲或未使用
(4)已连接:数据被ping住
详解:
dbf中的数据读到内存SGA,
buffercache中的数据和磁盘dbf文件中的数据是一致的,
叫这个数据是干净的。
里面还有一些内存空间没有使用
这是空闲或未使用的。
还有对这个数据块,
serverprocess在内存里面把它的数据修改了,
内存里面的数据,和磁盘中的数据就不一致了。
这时的内存里面的数据叫脏数据。
脏数据就需要写回dbf文件。
写回来以后它俩又一致了,又成干净数据了。
还有在内存里面的数据
目前serverprocess正在对它读或者正在对它进行写,
那个瞬间,这个数据块叫pin住了。
翻译叫连接了。
写完以后马上成了脏数据了。
PIN是读写一瞬间,
对内存的读写瞬间速度非常快。
已连接就是pin住。
随着数据库的运行,
buffercache慢慢在被使用,
其内数据块有脏的、干净的、空闲的
再次把dbf中的一个数据调到内存的时候,它优先使用空闲的没使用过的。
如果buffercache中所有的数据都使用过了,没有空闲的,
它接着使用干净的。
因为干净的数据意味着磁盘上有一个和它一样的数据。
这样新数据可以覆盖掉干净的块。
再需要原来干净数据块时,可以再把原干净数据调入内存。
也就是说对buffercache来讲
干净的或者空闲的这些数据,内存数据是可以被重用的。
对脏的能不能不直接覆盖?
不能!
我们为了使用这个脏的数据块占用的内存空间,
比如说里面全是脏的,
我还需要再使用内存的时候,
就会触发DBWn,将脏块写回磁盘。
写回磁盘后原块就成干净的了,
干净的就可以被重用了。
这是buffercache中数据块的几个状态
其实有linux命令可以监控系统设备性能
1、vmstat
vmstat是一个很全面的性能分析工具,
可以观察到系统的进程状态、内存使用、虚拟内存使用、磁盘的IO、
系统(中断、上下文切换)、CPU使用等
[oracle@redhat4 ~]$ vmstat
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
3 0 204 61596 39456 669880 0 0 13 35 303 174 48 22 30 0
2、iostat
iostat主要用于监控系统设备的IO负载情况,运行时显示系统的各项统计信息
[oracle@redhat4 ~]$ iostat
avg-cpu: %user %nice %sys %iowait %idle
47.79 0.05 22.11 0.43 29.61
Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn
sda 6.37 51.81 142.53 3267484 8989120
sda1 6.17 51.01 137.64 3216970 8680600
sda2 0.18 0.44 3.86 27814 243424
sda3 0.02 0.34 1.03 21716 65096
从这些数据可以知道 服务器整体是否繁忙。
不仅看命中率反馈问题,还要看物理读量的问题。
serverprocess在执行sql语句的时候,
需要从磁盘上dbf读数据的时候,
这个数据serverprocess从dbf里面读,
然后读到buffercache,然后从buffercache再返给用户。
查看SQL语句的执行情况
SQL> select /*hello*/ count(*) from t1 where OBJECT_ID=1;
COUNT(*)
----------
0
SQL> select /*hello*/ count(*) from t1 where OBJECT_ID=2;
COUNT(*)
----------
1
SQL> select /*hello*/ count(*) from t1 where OBJECT_ID=2;
COUNT(*)
----------
1
SQL> select sql_id,sql_text,executions from v$sql where sql_text like '%hello%';
SQL_ID
-------------
SQL_TEXT
--------------------------------------------------------------------------------
EXECUTIONS
----------
fvbb8qrfd0w5y
select /*hello*/ count(*) from t1 where OBJECT_ID=2
1
1vx8fabpy9dwv
select sql_id,sql_text,executions from v$sql where sql_text like '%hello%'
1
SQL_ID
-------------
SQL_TEXT
--------------------------------------------------------------------------------
EXECUTIONS
----------
8w6u2w729urmp
select /*hello*/ count(*) from t1 where OBJECT_ID=2
1
d3wjnjd4tm0p8
select /*hello*/ count(*) from t1 where OBJECT_ID=1
SQL_ID
-------------
SQL_TEXT
--------------------------------------------------------------------------------
EXECUTIONS
----------
1
参考博文:https://blog.csdn.net/xinzhan0/article/details/51933420