我们知道Oracle 里用户客户端是通过session连接服务器里的Server process进程来访问数据库的.
但是Server Process 并不会直接从数据文件中读写数据, 而是把数据先放入SGA里面的Database buffer cache(数据库高速缓存)里再进行操作, 最终依靠后台进程DBWR 将缓存里修改后的数据写回数据文件.
如图:
上图中, server process A想访问数据文件里的数据1, 首先会从缓存中找是不是已存在这些数据, 如果无, 就会将数据文件中的数据1放到缓存中. 然后就对缓存里的数据1进行访问.
当Server process对缓存里的数据进行读或写. 那么我们就是那个数据是
1.已连接的(PINNED)数据: 正在被Server Process读或写的数据.
2.Free空间(or unused): 未放入数据的其他缓存空间. 如下图:
3.干净(clean)数据: 缓存里还没被server Process修改的数据, 也就是缓存里和数据文件保持一致的数据.就叫做干净数据.
干净数据是可以被其他session 访问的, 如下图, 客户端Client B也同样想读取数据1, 而缓存里的数据1是干净的,所以Server Process B只需在缓存里读取(逻辑读)数据1就ok了, 避免了对数据文件的读取(物理读)
4.脏数据(dirty)数据: 假如上图的缓存里数据1被Server process A修改了, 那么缓存里的数据1已经与数据文件中的数据不一致了,那么数据1这时就成为了脏数据, 那么Server process B就不能读出那个脏的数据1了, 跟数据库里的不一致嘛, 否则就形成了 脏读.
这时我们就称数据1为已连接的(正在被Server process修改)和脏的.
5.那么如何避免Server Process B的脏读呢?
办法很简单, Oracle只需要再将数据文件的数据1 再一次放到缓存里的另1个地方中(free 空间). (又1物理读)
然后Server process B对其进行访问.
如下图:
这时缓存中又出现了1个数据1,只要Server process B 不对其修改,那么它就是干净的,又可以供其他session 读取.
6.假如这时DB buffer cache里面的free空间不足了,被各种数据占用, Server process如何读取数据1呢.
这时缓存中存在两种数据, 一种是脏数据, 另1种是干净数据. 这时有两种选择,一种是把缓存里的干净数据清理掉释放空间,另1种是清理脏数据.
如果清理脏数据,那么对应process serve对其的改动就丢失了. 所以oracle会清理缓存里的干净数据.
而干净数据也分已连接的和未连接的(对应session已经读取完成). 所以正确来讲Oracle会 释放缓存里未被连接的干净数据.
如下图:
如上图,虽然数据2也是干净的,但是正在被Server Process C读取, 而数据3是clean的而且是unpinned的, 所以就会把数据3释放, 放入干净的数据1,让Server process B读取.
7.假如这时DB buffer cache里面的free空间不足了,而且不存在为连接的干净数据,如何避免脏读?
如上图,这时就有两种选择,
1.就是等Server Process C读取完数据2, 这是数据就是unpinned的, 然后释放缓存里数据2的空间.
然后将数据文件的要读的数据放到缓存(物理读)
2.等Server Process A修改完脏的数据1后, 然后让DBWR后台进程将缓存里修改后的数据1写回数据文件(物理写), 这样缓存里的数据1又和数据文件中的一致了(干净了). 就直接可以让其他session读取了.
而 DBWR物理写比较耗时间.
所以大量用户进行写动作时, SGA里面的脏数据必然会很多, DBWR进程也相当繁忙, 通常这时对数据库数据的访问就会变慢了.
嗯,增大SGA(内存)是个好主意.!
但是Server Process 并不会直接从数据文件中读写数据, 而是把数据先放入SGA里面的Database buffer cache(数据库高速缓存)里再进行操作, 最终依靠后台进程DBWR 将缓存里修改后的数据写回数据文件.
如图:
上图中, server process A想访问数据文件里的数据1, 首先会从缓存中找是不是已存在这些数据, 如果无, 就会将数据文件中的数据1放到缓存中. 然后就对缓存里的数据1进行访问.
当Server process对缓存里的数据进行读或写. 那么我们就是那个数据是
1.已连接的(PINNED)数据: 正在被Server Process读或写的数据.
2.Free空间(or unused): 未放入数据的其他缓存空间. 如下图:
干净数据是可以被其他session 访问的, 如下图, 客户端Client B也同样想读取数据1, 而缓存里的数据1是干净的,所以Server Process B只需在缓存里读取(逻辑读)数据1就ok了, 避免了对数据文件的读取(物理读)
4.脏数据(dirty)数据: 假如上图的缓存里数据1被Server process A修改了, 那么缓存里的数据1已经与数据文件中的数据不一致了,那么数据1这时就成为了脏数据, 那么Server process B就不能读出那个脏的数据1了, 跟数据库里的不一致嘛, 否则就形成了 脏读.
这时我们就称数据1为已连接的(正在被Server process修改)和脏的.
5.那么如何避免Server Process B的脏读呢?
办法很简单, Oracle只需要再将数据文件的数据1 再一次放到缓存里的另1个地方中(free 空间). (又1物理读)
然后Server process B对其进行访问.
如下图:
这时缓存中又出现了1个数据1,只要Server process B 不对其修改,那么它就是干净的,又可以供其他session 读取.
6.假如这时DB buffer cache里面的free空间不足了,被各种数据占用, Server process如何读取数据1呢.
这时缓存中存在两种数据, 一种是脏数据, 另1种是干净数据. 这时有两种选择,一种是把缓存里的干净数据清理掉释放空间,另1种是清理脏数据.
如果清理脏数据,那么对应process serve对其的改动就丢失了. 所以oracle会清理缓存里的干净数据.
而干净数据也分已连接的和未连接的(对应session已经读取完成). 所以正确来讲Oracle会 释放缓存里未被连接的干净数据.
如下图:
如上图,虽然数据2也是干净的,但是正在被Server Process C读取, 而数据3是clean的而且是unpinned的, 所以就会把数据3释放, 放入干净的数据1,让Server process B读取.
7.假如这时DB buffer cache里面的free空间不足了,而且不存在为连接的干净数据,如何避免脏读?
如上图,这时就有两种选择,
1.就是等Server Process C读取完数据2, 这是数据就是unpinned的, 然后释放缓存里数据2的空间.
然后将数据文件的要读的数据放到缓存(物理读)
2.等Server Process A修改完脏的数据1后, 然后让DBWR后台进程将缓存里修改后的数据1写回数据文件(物理写), 这样缓存里的数据1又和数据文件中的一致了(干净了). 就直接可以让其他session读取了.
而 DBWR物理写比较耗时间.
所以大量用户进行写动作时, SGA里面的脏数据必然会很多, DBWR进程也相当繁忙, 通常这时对数据库数据的访问就会变慢了.
嗯,增大SGA(内存)是个好主意.!