oracle学习笔记 Oracle日志核心意义_快速提交_写缓存



oracle学习笔记  Oracle日志核心意义_快速提交_写缓存

oracle实例有
dbf、buffercache、logbuffer、redolog


一)oracle中的事务


oracle有一个原则
所有已提交事务oracle保证不会丢失


先退出目前会话
SQL> exit


然后重新登陆
[oracle@redhat4 ~]$  sqlplus / as sysdba
这时的这个会话是干净的没有任何的事务


执行一条命令

SQL> delete from t1 where rownum=1;

1 row deleted.

从t1删了一行数据


登陆了数据库以后,然后删了一行数据
这个时候其实是一个事务开始了


这时再敲了一个命令commit,叫提交
这就是一个事务


可以这么认为
一个事务是由一条和多条增删改数据组成一个事务
就是一条或多条DML语句


关系数据库的标准语言为结构化查询语言(Structured Query Language)
最多可分为六个类型
数据查询语言(DQL:Data Query Language) 如:SELECT语句
数据操作语言(DML:Data Manipulation Language) 如:INSERT、UPDATE、DELETE等语句
数据定义语言(DDL:Data Definition Language) 如:CREATE、DROP、ALTER等语句
数据控制语言(DCL:Data Control Language) 如:GRANT、REVOKE、DENY等语句
事务处理语言(TPL:Transaction Processing Language) 如:BEGIN TRANSACTION、COMMIT、ROLLBACK、SAVEPOINT等语句
指针控制语言(CCL:Cursor Control Language) 如:DECLARE CURSOR、FETCH INTO、UPDATE WHERE CURRENT等语句


习惯上有人把DQL并入DML,也有把DCL并入DDL的
很多分类方法没有指出CCL


事务和oracle的一致性关系非常紧密
很多人就是因为在事务这个概念上没有注意
最后导致数据库的数据被损坏


在实际中事务很简单
就如刚才讲的原理,讲课内容还有实际操作都很简单
所以很多人在事务上没有引起重视
实际工作中经常容易犯的一些和事务相关的错误
知道后再看就会很后怕


事务就是由一条或多条增删改数据组成


比如我们登录一个数据库以后
开始一条delete语句
一个事务开始了
然后commit一个事务结束了
commit以后我们再输入一条增删改数据的时候
一个事务又开始了


我们可以这么认为一个事务的开始和结束是在两个commit之间


我刚登陆以后
和第一个commit之间是一个事务


这个commit回车以后
接下来又输入一些增删改数据以后
再commit
这两个commit之间我们叫一个事务


在提交以后


执行
SQL> delete from t1 where rownum=1;

1 row deleted.


delete删了这个数据块的一行数据
在内存里删的
删了以后那个buffer块就成脏块了
buffer中的脏块和dbf中的块就不对应了
然后我们提交了commit


oralce有原则所有已提交事务不会丢失
提交后我们希望提交了就不会丢失了


二)事务提交方法


1)假设的方法


一种办法是
buffer中的块修改提交了把内存中的块它写到磁盘上,这个可以
然后提交成功


但是有问题
前面的例子还好一些,我只修改了一个块
比如说我执行了delete修改了12个块
执行了一个修改,修改了30个块
执行了一个删除,300个块
而且这300多个块分布在磁盘的各个位置
然后这三个语句执行完了以后commit
这时候如果按照刚才我们假设oracle需要将buffer里面的所有的数据块写到磁盘上
然后commit才会成功


commit成功就是

SQL> commit;

Commit complete.

SQL>


commit后光标返回了我们认为就成功了


因为它修改了这么多的块
这些块分布在buffer里,对应在磁盘上的这些块分布在很多位置
commit以后
我们需要将所有的buffer写到磁盘上
这时因为你的buffer分布在很多位置要做很多次寻道seek track
而且这里还有磁盘IO的一个限制


就是我们的提交光标需要等一段时间才能返回


这个时候对用户来讲
删除一些数据以后
然后commit,假设等了两分钟
我们的用户就感觉到oracle很慢
如果用户连到数据库上做任何操作光标马上返回
用户就会认为oracle很快
至于oracle后台怎么工作他不关心
不会原谅这些buffer正在往磁盘上写所以速度比较慢
用户就感觉你数据库慢
我们希望的是用户提交以后快速的返回光标

所以说我们commit以后
oracle将所有的buffer写到磁盘上这样不现实


2)实际的方法


在一个会话session登上来以后
执行了三条语句
第一个语句修改12个块
第二个语句修改了30个块
第三条语句修改了300个块
在修改的过程会产生很多的日志
这些日志在这个会话的pga里面产生


产生以后会批量的快速的写到logbuffer里面去
logbuffer因为有空间限制、时间限制等等
LGWR会相对比较快速的把日志写到redolog里面去


会话serverprocess修改块的过程中产生很多日志
日志写到logbuffer,logbuffer由后台LGWR写到磁盘上
整个过程产生的日志都在logbuffer里面,logbuffer也会往redolog里写


oracle在commit的时候
一提交这个时候oracle就会触发LGWR把logbuffer的日志写到磁盘上


也就是commit的时候
commit没有触发DBWR将这些内存buffer中的文件将这些buffer写回磁盘
oracle只做一件事情触发LGWR把logbuffer写回磁盘的redolog


好处
第一
serverprocess在修改的过程中产生的日志写到logbuffer里面
logbuffer将来写到redolog里面去
我们在一个时间点只写一个redolog
每一个redolog在磁盘上都是一块连续的空间
所以说产生的日志通过logbuffer到redolog写的时候
寻道的次数会很少
我们产生的日志是很集中的写到一个redolog里面去
而且是顺序写
它和你修改的buffer写回dbf来的时候是离散的各个位置写不一样


第二
serverprocess在修改数据块的过程中产生的日志写到logbuffer
在修改buffer中块的过程中
logbuffer日志由LGWR不停的往redolog里写
而且写的速度还很快
因为都是顺序写没有多少寻道
当执行完了以后commit提交的时候
oracle只需触发LGWR把剩余的日志写到磁盘上就可以了


第三
日志记录了数据块的所有的改变
一个数据块改变了和磁盘上就不一样了
我提交的时候我没有把buffercache里的脏块写回dbf
但是把脏块的修改记录以日志的方式写下来了
将来如果数据库突然崩溃了
对磁盘数据块来讲它的修改可以通过日志重新去做一遍


也就是对oracle来讲
我们把日志给保存起来了
相当于把对数据块的修改也保存起来了
将来数据块的修改如果丢失了
可以用日志重显出来
日志就起这个作用的


所以我们提交的时候
oacle不需要将这么多的块写回dbf
只需写很少一块日志过来就ok了


这就是oracle的commit为什么这么快


举个实例
SQL> select count(*) from t1;

  COUNT(*)
----------
     50316


这个表有5万多行


然后
SQL> delete from t1;

50316 rows deleted.


将t1表所有的数据给删除


在这个过程中会大量的修改buffer产生大量的日志
日志写到logbuffer里面
然后被logbuffer里的LGWR批量写到redolog中


3)快速提交


回顾一下
客户会话连入数据库
给serverprocess分配PGA
sql修改数据块产生日志
日志由PGA写到logbuffer


logbuffer很小
在oracle9i以前logbuffer的大小一般不超过3M,非常小
到oracle10G以后也就是十几兆
设大了也没有意义浪费空间


进程LGWR把日志从logbuffer顺序的写到日志文件里面去
因为是顺序的写所以速度会很快
这就是oracle日志的整个的一个工作过程


logbuffer一共才3M
LGWR每隔3秒钟或者logbuffer的空间日志超过一M的时候都会触发LGWR往磁盘写
所以正常情况下logbuffer里面的日志不会超过一个兆
也就是说logbuffer本身就很小
LGWR写的也很快而且LGWR持续的往磁盘写


有大量的会话连上来要修改buffer,产生大量的日志
都写到logbuffer里面去
LGWR会频繁的往磁盘写


对其中一个会话来讲
它有commit提交
这时它并不把这些buffer写到磁盘上
提交的时候
只是把logbuffer里面那一点点日志给写到日志文件里面去
所以说我们提交的时候速度很快


delete from t1;
删除了很多行
块被修改了产生了很多日志
日志写回了磁盘
脏块还在内存里


我们现在提交一下


SQL> commit;

Commit complete.

SQL>


提交马上就返回了


提交的过程只做一件事情
只是把logbuffer里面的日志清了一下
把logbuffer中的剩余日志写到了redolog中
日志往磁盘写了一下
没有实际把buffer写回磁盘dbf


所以说对用户来讲
我commit速度这么快
就认为数据库oracle很快
一旦光标返回,就可以做下一件事情了


这样日志实现了快速提交
提交非常快,马上就认为成功了


三)日志和计算机缓存


前面我们说过缓存,一种是读缓存,一种是写缓存


计算机中
只读缓存是把数据块调到内存,
读的时候可以到缓存里面去找
cpu去读这个块,只能读这个块
如果cpu要修改这个块,不能直接在内存修改
要修改需要直接修改磁盘上的
修改磁盘会产生IO


读缓存只对读有意义对写性能很低下
它只是能提高读的性能对写没有什么性能提高


oracle因为实现了日志机制
修改了一个buffer块产生logbuffer日志马上写回磁盘redolog
commit以后日志保证写回来
commit就成功了


在oracle里面
oracle的各种buffercache实现了写缓存
对写的块和对产生的日志写回磁盘进行缓存
所以对oracle来讲实现了写缓存
日志写缓存的实现是通过日志的buffercache也就是logbuffer
它不仅仅对读有意义,对写也有意义


oracle的buffercache
不仅能大幅的提高读性能,还能提高写性能
在整个的计算机里面
oracle数据库里面能够提供写缓存的只有两个地方


oracle的buffercache可以写缓存所以说oracle的性能很高


还有一个地方
我们的数据库都建在各种类型的存储上,存储有buffer,buffer上有电池
也就是存储的buffer支持写缓存
存储中的单个硬盘上本身也有缓存,只提供读缓存


在整个oracle的运行环境中
buffercache提供写缓存
文件系统也有缓存只提供读缓存,不能写缓存


一般内存和磁盘的数据交换都要经过文件系统
内存的数据在从磁盘读取时要经过文件系统的读缓存
内存的数据在向磁盘写入时也要经过文件系统但此时文件系统不提供缓存


当然oracle的存储体系实际工作中很少建在文件系统上
这样读写也不经操作系统的文件系统了


oracle读数据
先从 磁盘 到 存储的buffer 然后到文件系统的buffer 然后再到buffercache
这里是读缓存,读大家都支持
所以数据一步步从磁盘到内存


oracle写数据时
因为redolog也在文件系统上也在存储上
LGWR写的时候会绕过文件系统的缓存
即绕过文件系统中的cache,这个cache只能缓存读
直接将redolog写到存储的缓存里面
然后存储会控制在适当的时候写到磁盘里面去
redolog在磁盘上


存储的写缓存通过电池来实现的,为了保持数据不丢失要使用电池


oracle写数据
从内存中的logbuffer,绕过文件系统,到存储的缓存,最后到磁盘中的redolog


我们commit成功了
实际上数据使用LGWR进程只是把数据从logbuffer写到存储的cache里面去了


到底有没有写到磁盘上,LGWR不知道,它被存储骗了


存储告诉LGWR我已经写到磁盘上了
实际它在存储的buffer里面
但LGWR认为已经写到磁盘上了


当然存储有自己的机制来保证数据能够写回磁盘使数据不会丢失
如果这时出错数据库就会有数据丢失产生不一致


比如说存储出问题了,电池没电了耗完了
这时候数据也会丢失
这时候redolog也可能损坏
有这么个地方需要大家注意


学oracle要学存储因为存储中的磁盘是所有数据的最终去处


前面讲了如何确保已提交的数据不会丢失
commit提交的时候
保证我这个事务所修改的所有数据块所对应的日志已经写到redolog里面去了


将来数据块如丢了
一个事务所修改的所有数据块所有的buffer产生的日志都写到redolog里面去了
数据库突然崩溃了,就是buffer里面的脏块没了
数据库下次启动以后
就可以使用这些redolog把那些丢失的脏块再重新构造出来
就是能够将数据库恢复到崩溃以前的那个时刻
也就是不会出现数据丢失


oracle数据库数据恢复有 实例恢复(INSTANCE RECOVERY) 和 介质恢复(MEDIA RECOVERY)
上面说的恢复实际是实例恢复


实例恢复是Oracle实例出现失败后,Oracle自动进行的恢复。
数据库出现实例故障,例如:意外掉电、后台进程故障
或预料中使用ABORT命令终止数据库实例
在启动数据库时就会发现实例故障,此时就需要实例恢复
实例恢复是数据库自动进行的,可以将数据库恢复到故障之前的事务一致性状态
它可以确保BUFFER CACHE中的数据不会丢失
只用到redolog,不使用归档日志


介质恢复主要用于介质故障引起数据库文件的破坏时使用
是当存放数据库的介质出现故障时所做的恢复


介质故障是当一个文件、一个文件的一部分或磁盘不能读写时出现的故障
文件错误一般指意外的错误导致文件被删除或意外事故导致文件的不一致
这些状态下的数据库都是不一致的,需要DBA手工来进行数据库的恢复


介质恢复用在丢失或损坏数据文件或者丢失了控制文件的情形
将还原的数据文件恢复成当前数据文件
还能够恢复数据文件异常脱机时没有来得及做检查点操作丢失的变更
介质恢复使用归档日志和联机日志
但必须由命令显式调用,即手工进行


如果在在线后备发现实例故障也要用介质恢复


oracle是通过日志保证已经提交的数据不会丢失
同时也讲了oracle如何实现快速的提交
一提交马上commit成功
也给大家讲了oracle如何实现写缓存
buffercache如何实现写缓存
LGWR绕过操作系统直接写入磁盘,但是绕不过存储的写缓存



2016年10月29日

                                                                                   文字:韵筝






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值