DBAI 第一章 ORACLE体系结构四Word格式.docx
《DBAI 第一章 ORACLE体系结构四Word格式.docx》由会员分享,可在线阅读,更多相关《DBAI 第一章 ORACLE体系结构四Word格式.docx(38页珍藏版)》请在冰豆网上搜索。
上图可以通过当前会话来查看服务器进程号和用户进程号。
用户进程号就是客户端进程,上图绿色框LOCAL=YES和BEQ表示客户端通过IPC进行本机连接。
客户端进程由V$PROCESS.CLIENTPID指出,看蓝色框值是5112,我们可以通过ps查看该进程是sqlplus客户端。
而红色框是服务器进程是SPID(SERVERPROCESSIDENTIFIED),值为5114
可以通过ps查看是10g的服务器进程。
⊙连接:
连接是客户端到数据库实例的物理通道
连接可以经过网络NET8或者通过IPC(内部协议接口)实现
一个典型连接
⊕客户段进程←→专有服务器进程(专有模式)
⊕客户段进程←→调度器进程(共享模式)
我们来用SQLPLUS来建立一个连接
当前连接上有一个会话和一个进程,会话ID=16,进程地址070000004B481688
上图执行完setautoton后,该专有连接方式的连接上,出现两个会话,而进程地址相同。
SID=18就是用于统计时用的会话。
当关闭统计时,统计的会话自动关闭,只有原始会话
用ps查看该进程
我们用disconect关闭连接,但是进程还在
会话也在。
只是物理通道没有了,我们来看内存使用情况
内存资源仍然被占有,所以单个连接可以有多个会话关联到单个进程,即使在专有模式。
单个连接可以有0个、1个或者多个会话,但是专有模式单个会话对应单个进程。
在没有连接的情况下,会话和进程可以一直存在。
我们再来看共享服务模式
我们看到连接到了S000共享服务器进程。
但是当该会话休眠时会怎么样呢
前面的共享服务器去服务别的会话了,所以当前会话只是跟调度程序D000关联,进入了响应队列。
那当前会话再次活动时会怎么样呢
故意激活另一个会话,好让刚才S000服务于它,那当前会话可能就不是由S000来服务了。
上图看到由S001来服务了,这里大家应该联想到了司机和船长了吧。
这些核心的后台进程涉及到很多内核的操作,它关系到ORACLE正确安全有效的运行,并直接跟我们的实例中个内存模块和其它后台进程关联着,所以要了解后台进程的机制,要温固我们前面内存的知识。
后台进程也分强制后台进程和可选后台进程。
强制后台进程
=======
我们首先按时间触发次序,来介绍第1个强制后台进程LGWR。
谈到LGWR,他关联最主要的内存组件是REDOLOGBUFFER。
另外还涉及REDOLOGFILE,它是物理组件。
REDO是我们记录了数据库提供的服务的所有交易历史,包括买卖和退货,也就是REDO和UNDO。
UNDO其实也是记录在REDO中一REDO记录形势存在,只是它的日志关系到的是保留回退的数据,所以也记在REDO里了。
那这些交易历史记录必须有一个地方保存,我们会有三个地方保存
⊙redobuffer
⊙redologfile
⊙archivelogfile
这3个部分都有相应的进程去完成,并有一套严格的触发机制。
而我们图的右边讲了从redobuffer=>
redologfile的触发机制,
LGWR工作(触发将redobuffer的日志项写入redologfile)的主要条件如下:
1.用户提交
2.有1/3重做日志缓冲区未被写入磁盘
3.有大于1MB重做日志缓冲区未被写入磁盘
4.超时(每3秒)
5.DBWR需要写入数据的SCN号大于LGWR纪录的SCN号,DBWR触发LGWR写入
--这个例子最好跳过,太难
为了更好的了解这三个部分的运作,我们也用一些生活化的故事来描述。
这个故事比前面都要复杂,而且也跟很多性能有关系,涉及很底层知识我们就不讲了,希望能更通俗的理解它的机制。
我先画出ORACLE各组件的名字及流程图,然后大家照着这个图去理解我们这个故事。
[1]serverprocess->[2]redocopy->[3]redoallocation->
[4]redocopy->[5]redoallocationrelease[6]redologbufferfinished->[7]->modifyblock[8]redoentryvalid->[9]releasesredocopy->[10]LGWR->logfile[10-1]1/3
[10-2]_log_io_size
[10-3]commit
[10-4]dbwr
->[11]redowritingfinished->[12]dbwr
1-12是这个redo请求到redo的数据到物理数据文件的确认过程,10下面有4个触发条件,分别是lgwr的触发条件。
我们用一个寄信到收到信来描述这个流程。
我们先罗列出几个主要的机构和人员
一个邮局有:
⊙8个信件登记员
⊙1个信件登记归档员
⊙1个信件登记管理员
⊙多个发送邮递员
⊙多个接收邮递员
比如小丽是某厂的收发室收发员,今天要发一批寄到北京的信(是基于一批同一目的的信),我再把前面的流程发一遍,大家对照下。
⊙[1]serverprocess
⊙[2]redocopy
⊙[3]redoallocation
⊙[4]redocopy
⊙[5]redoallocationrelease
⊙[6]redologbufferfinished
⊙[7]modifyblock
⊙[8]redoentryvalid
⊙[9]releasesredocopy
⊙[10]LGWR->logfile
⊕[10-1]1/3
⊕[10-2]_log_io_size
⊕[10-3]commit
⊕[10-4]dbwr
⊙[11]redowritingfinished
⊙[12]dbwr
我们来看邮寄的对应流程
⊙[1]她打电话到邮局
⊙[2]邮局会分配一个信件登记员A先记录这些信来自哪里,寄到哪里等信息,信件登记员A来负责这件事情。
⊙[3]请求信件登记管理员,让他帮忙评估这次登记所需要帐本的大小,并提供此大小的帐本。
信件登记员A请求信件登记管理员,让他帮忙评估这次登记所需要帐本的大小,并提供此大小的帐本。
⊙[4]信件登记员A在此帐本上登记这次发往北京信的信息.
⊙[5]信件登记管理员服务完信件登记员A,服务其它信件登记员
⊙[6]信件登记员A完成这批信的登记
⊙[7]请求发送邮递员去收发室拿这批信发到邮箱。
那为什么先登记再发送到邮箱呢?
因为如果信件登记员A不先登记信息,那小丽不打算发信的话,要回退,邮递员会忘掉刚才是从哪儿拿来的.
⊙[8]信件登记员A标注这次登记有效
⊙[9]信件登记员A服务完小丽这次请求,将服务其它请求
前面知道redo分下面三大步
⊕1redobuffer
⊕2redologfile
⊕3archivelogfile
这前面9步是完成这三大步的第一步(redo生成,并修改了相关的块),接下来是第二步是生成redologfile
⊙[10]LGWR->logfile
⊕[10-1]1/3
邮局会有一个记录整个邮局每天的信件记录进行归档的信件登记归档员。
把所有8个信件登记员这次没有被信件登记归档员归档的条目进行归档。
假如整个邮局最大可登记信件交易量是8000封。
而且这8000封物理上顺序分配。
所有邮箱里的信满三分之一(2400封信了),这些登记的信的有效条目需要进行确认归档,以便这些信通过火车飞机传递到不同的目的地时,想返回,而找不到如何回到原来寄信人的位置
⊕[10-2]_log_io_size
满1000封信了,可以设置
当然还有比如每天凌晨9点
⊕[10-3]commit
小丽这批信确认一定要发送到北京,那一旦信件登记员登记的条目被以外丢失,而信又还在邮局的邮箱,还可以从信件归档条目里找到,这些信要寄的位置
⊕[10-4]dbwr
确定要把信发到北京时
⊙[11]redowritingfinished
⊙[12]dbwr
这些信最终通过火车飞机等送到北京的邮局前由信件登记归档员对这些信做信件登记归档。
我使用一个行列表格来说明:
进程动作
生活例子
[1]serverprocess
[1]她打电话到邮局
[2]redocopy
[2]邮局会分配一个信件登记员A先记录这些信来自哪里,寄到哪里等信息。
信件登记员A来负责这件事情
[3]redoallocation
[3]请求信件登记管理员,让他帮忙评估这次登记所需要帐本的大小,并提供此大小的帐本。
[4]redocopy
[4]信件登记员A在此帐本上登记这次发往北京信的信息
[5]redoallocationrelease
[5]信件登记管理员服务完信件登记员A,服务其它信件登记员
[6]redologbufferfinished
[6]信件登记员A完成这批信的登记
[7]modifyblock
[7]请求发送邮递员去收发室拿这批信发到邮箱。
✧为什么先登记再发送到邮箱呢?
✧因为如果信件登记员A不先登记信息,那小丽不打算发信的话,要回退,邮递员会忘掉刚才是从哪儿拿来的。
[8]redoentryvalid
[8]信件登记员A标注这次登记有效
[9]releasesredocopy
[9]信件登记员A服务完小丽这次请求,将服务其它请求
1redobuffer
2redologfile
3archivelogfile
这前面9步是完成这3大步的第1步
redo生成,并修改了相关的块
[10]LGWR->logfile
[10-1]1/3
[10-4]dbwr
[11]redowritingfinished
[12]dbwr
我们用一个SQL来看下lgwr和dbwr是如何触发
这儿大家注意3个session的时间点
Altersystemcheckpoint干嘛的,谁知道?
此命令触发了一个全局检查点,就是后面要讲得CKPT进程
然后CKPT进程触发DBWR讲数据缓冲区的脏数据(简称脏缓冲)写入到数据文件里,
所以altersystemcheckpoint后,你修改了的数据即使没有提交,也会写入到数据文件,明白了吧?
根据前面执行的时间及对lgwr和dbwr的影响我们画出这张图
⊙也就是说小丽即使提交了10000,数据文件里还是5000的值
⊙而小王没有提交,数据文件反而已经写进去了更新后的值8000,因为DBWR前已经更新成8000了。
那这时准确的数据是什么呢
所以我们看到数据文件现在的值全错了,我们这时在查询小王薪水时需要小王从8000变为5000,小丽从5000到10000,那怎么让小丽从5000到10000,让小王回到5000呢?
我们看下图
要让已经提交为10000元的小丽实际数据文件从5000到10000,则需要应用logfile前滚到10000。
要让未提交小王实际数据文件从8000回到一致性读的5000,则需要应用undofile回滚到5000。
我们这里主要涉及到两个文件
⊙LOGFILE―― 日志记录了修改成8000前的记录是5000写到UNDOFILE的UNDO块里,而日志文件只是记录了UNDO块的改动向量,所以我们称这时的REDO为记录UNDO改动的REDO,也就是UNDO性质的REDO。
它的改动向量是8000变成5000,这个5000记录在UNDO块中,并记录了这个UNDO块所关联的实际数据文件DATA块地址,我们看到正真回滚不是LOGFILE中UNDO性质的REDO来做的,而是需要UNDOFILE来做,这样避免了回滚操作读取在线日志,从而减少了对LGWR的冲突,让日志文件通常只用于写操作,而不去读操作。
要读UNDO就要去读UNDOFILE,这就是ORACLE和其它数据库区别的本质。
⊙UNDOFILE―― 将所有数据前滚后,发现有些事务没有提交的标志,此时若用户发出ROLLBACK,或者一致性读的时候,那么将应用对应事务的UNDO链,回滚到事务前的状态,8000的事务前的状态是5000,这个5000是在回滚段块上(UNDO块),这时才找到小王准确的值5000。
所以得到小王值的是在UNDOFILE回滚段里,并得到上图红色框。
上面的知识点,大家有问题没?
LGWR、DBWR都只是写,WR就是Write嘛
LGWR主要负责将重做日志缓冲区(redologbuffer)的数据写入重做日志文件(redologfile)。
当数据被修改的时候,系统会产生一个重做日志并纪录在重做日志缓冲区内。
而DBWR主要负责将数据缓冲区内的脏数据(脏缓冲)定期写入数据文件。
好,我再帮大家理一理
因为LOGFILE里会有UNDO性质的REDO,而UNDOFILE里也有这部分UNDO数据,我们以前介绍个一致性读(CR),
那我们在SELECT一个未提交的块时,需要一致性读。
那一执行读应该究竟去读LOGFILE里UNDO性质的REDO呢?
还是直接读UNDOFILE里的UNDOBLOCK?
对,会读UNDOBLOCK,这样就不用去读LOGFILE了,LOGFILE是LGWR在写的,这样就没有一致性读的IO跟LGWR竞争了。
好,我再给大家说下前滚和回滚。
回滚是读取UNDO,比如ROLLBACK,刚才说的一致性读,都会读取UNDO的信息,回滚到更改前的值。
而前滚一般用在恢复上,这里涉及到备份恢复,又超纲了。
比如你有5000块前,现在update成10000块了,而且还commit了,但是这时候突然断电了,你的10000块钱还没落实到你口袋,就消失了。
那么来电了,数据库要进行崩溃恢复,这时就需要前滚,把提交的部分前滚,你的5000就变成10000了,然后前滚的时候还会检查到未提交的,那未提交的就要回滚,这就是恢复过程中前滚和回滚的区分。
恢复的时候大家记住一句话,先前滚再回滚
我再整个例子,这块大家第一次容易晕,
你如果是
周1
周2
周3
周4
存5000元
COMMIT
存4000元
如果数据在周四你刚存完4000还没来得及COMMIT的时候就DOWN了,坏了
你得用备份来还原恢复吧,我们假设有周1做的备份,周一做备份的时候当时账户还没有钱。
好,那我们先把周1的备份还原,还原后还不行啊,你存的钱都丢了,还得用日志来恢复,那恢复就要用到重做日志。
这个时候我们的恢复目标是要恢复到帐号里有10000元,对吧?
那恢复的过程是前滚周1的5000,周2的5000,周3的COMMIT,周4的4000,直至最后一笔交易,那现在帐户里是不是14000
全部前滚完就是14000,但是14000是不正确的,因为我在周4存4000的时候,没有按确定,数据库就崩了,正确帐户余额是10000。
那是不是得把周四的交易(改动向量)回滚,交易我们可以理解成REDO的向量
回滚也要应用REDO(UNDO性质的REDO),这个REDO会去找UNDOFILE
整个过程就是:
先从redo(REDO性质的REDO)找到DATAFILE,再应用REDO记录的数据来写DATAFILE(前滚),再从REDO(UNDO性质的REDO)找到UNDOFILE,再应用UNDOFILE的块,完成回滚
这里涉及到日志写、脏缓冲写、UNDO数据脏缓冲写和REDO数据脏缓冲写有先后次序的问题。
第一个问题
UNDO、REDO数据脏缓冲写顺序
==================
那如果dbwr将小王从5000写到8000元,如果这时候停电,小王的当前数据文件是8000,正确的是5000,这5000的记录redobuffer或者logfile有,它是UNDO性质的REDO。
但是可能会出现类似DOWN机,停电等事件,内存马上被刷了,那如果没有先没记录UNDO性质的REDO,你如果日志、脏缓冲区里先记录了5000变为8000,此时数据库down,那要想小王回到5000元是不可能的了,因为人事部不知道,小王加薪前工作5000。
当然小王是开心死了,没有存3000,结果拿到了8000。
这是绝对不允许的,所以在修改一个数据前,第一步是保存修改前的值后(包括记录UNDO性质的REDO、写UNDOFILE的脏缓冲)才能做真正的修改。
第二个问题
日志缓冲写、脏缓冲写顺序
我们知道脏缓冲是业务数据的变化记录在内存的区域,它通过dbwr写到磁盘数据文件,但是ORACLE为了提高磁盘写的效率,采用了延迟内存写的技术,会很长时间才会从SGA中数据库高速缓冲中脏缓冲写到磁盘。
那如果这么长时间的内存数据一定很多,如果突然停电,意味着要丢失脏缓冲的所有修改。
这会造成一些客户明明提交了一笔交易(比如存入100万),却最后被内存丢失了,磁盘里再也没有这笔交易了,这在ORACLE是绝对不允许的,数据的准确性和安全性是数据库最重要的基础,所以ORACLE会强制在COMMIT后已经确认的交易必须从内存到磁盘得到确认,但是如果通过脏缓冲确认会对性能有很大影响,于是这项任务就交给LGWR来完成,一旦有COMMIT就必须从REDOBUFFER写到磁盘的LOGFILE。
这样安全就得到保证。
正是因为这一点,我们如果先在脏缓冲了确认了一笔交易,再记录这比交易的历史,那会存在很大风险,如果写脏缓冲成功,并做COMMIT,接着数据库DOWN了,还没来得及记录日志,那这笔100万就完全丢失了。
因为100万只记录在内存,没有记录在LOGFILE,也没有记录在DATAFILE,这是非常危险的。
所以ORACLE强制先写日志BUFFER,再写脏缓冲。
我们总结下修改数据的步骤
修改数据的步骤
========
⊙写UNDOFILE变更的日志改动向量,如8000修改前的值5000到UNDOFILE的这次改动向量到REDOBUFFER。
⊙写8000修改前的值5000写到UNDOFILE对应的脏缓冲。
⊙写5000修改后的值8000到DATAFILE的这次改动向量到REDOBUFFER。
⊙写5000修改后的值8000到DATAFILE对应的脏缓冲。
接下来我们来学习一个非常重要的后台进程,检查点进程。
检查点
检查点是一个维护数据库一致性的重要的后台进程,跟DBWR,LGWR及备份与恢复原理有着密切的联系,也涉及到非常多的理论,所以大家要学习它的时候请回忆下我们前面学过的内存和进程的架构。
检查点是一个数据库事件,它将已修改的数据从脏缓存里刷新到磁盘,并更新控制文件和数据文件的一致性信息。
它是一个数据库一致性的快照,可以针对一个文件,一组文件,一个实例,所有集群实例。
检查点只是一个事件,触发了别的进程,而自己只是改变一些数据文件和控制文件里的一致性信息。
它触发的是DBWR,真正干活的是DBWR。
当检查点触发时,会将记录在检查点队列里的脏缓冲中生成的改动刷新到磁盘,这里涉及检查点队列。
关于检查点那么多概念我们可以举一个简单生活的例子:
我们坐火车到深圳火车站旅游集散中心,火车站有专门的等候旅游大巴的站台,有专门的交通协调员会拉一根绳子,为我们旅客排队。
旅行团可以理解成是重做向量改动的实体,每个旅行团我们看成ORACLE的一个块,旅行团的每个人好比是ORACLE中的一行记录,每个旅行团的个体的动作在ORACLE中称为改动向量,比如小王去厕所。
而等待排队的是谁?
只需要旅行团的导游小姐,导游小姐就好比数据块的块头BUFFER。
所以每个旅行团导游小姐在开始排队到坐上大巴这一任务可能有一系列的动作(改动向量),而这个等待队列是先进先出的,最先排队的,最先得到旅游大巴的服务。
但是这时导游小姐排在第5位。
旅行团的小丽去买饮料,表示一个块的行的变更,有了改动向量,但是导游小姐仍然排在队列的第5号位置。
也就是导游小姐的位置不受旅行团每个旅客的影响。
而交通协调员当排队长度达30人的时候统一放前10个旅行团去坐大巴。
接着又有10个新的旅行团的导游来排队的时候,交通协调员再次放行。
这将是我们后面将到的快速检查点。
另外放行的规则非常多,还有比如到固定时间就得放人,我们后面详细介绍。
开始备课(2010.08.19)
上节课我们学习了ORACLE非常重要的两个后台进程:
LGWR和CKPT,我们还是来简单复习下。
第一个问题:
我们知道ORACLE后台进程也分强制后台进程和可选后台进程