拓扑园

  • Oracle性能优化
  • Oracle项目案例
    • Oracle近期项目案例(目录)
    • Oracle实战问题解析(目录)
    • Oracle数据库名变更流程(2种方式)
    • Oracle数据库目录更换流程(使用Oracle的clone工具)
    • Oracle数据库迁移方案(目录)
    • 标准化文档系列
  • Oracle基础知识
    • LLL的Oracle培训(分类)
    • LLL的docker培训(分类)
    • 标准化文档系列--(分类)
    • Oracle核心经典分析(分类)
    • 图灵小队----(分类并包含以下文章)
    • --MySQL8.0/Oracle/Memcached/Redis等安装配置于RHEL/OL6/7/8.X系列-运行环境最优配置
    • --PG安装配置于RHEL/9X系列-运行环境最优配置
    • --自动维护任务详解-开启、关闭信息统计收集(统计信息)
    • --图灵小队—Oracle/PostgreSQL下创建一个用户测试表(自行定义数据行)
    • --图灵小队-Oracle存储过程导出表的明细_UTL_FILE(文章)
    • --图灵小队-Oracle数据库删除/卸载操作指南(文章)
    • --图灵小队-Oracle常用性能查询SQL语句(文章)
    • --图灵小队-Oracle数据库上线前检查(文章)
    • --图灵小队-Oracle常用SQL语句(文章)
    • --图灵小队-Oracle脚本合集(文章)
    • --图灵小队-Oracle技巧记录(文章)
    • ADG
    • RAC
    • ASM
    • OGG
    • RMAN
    • EXPDP/IMPDP
    • 工厂数据导入导出系列
  • MySQL相关
  • Linux
    • kubernetes
    • docker
    • Linux
    • PHP
    • Nginx
    • haproxy
    • mail
    • 网站
    • 域名
    • 网址收藏
  • 数据中心
    • 新框架系统集合
    • 工作文档
    • EBS数据文件扩容
    • VMware虚拟化
    • EBS系列
    • 大数据
    • SVN
    • zabbix
    • SAP
    • 备份相关
    • FC交换机
    • SVN
  • K-Studing
    • LG-MySQL
    • LG-Docker/K8S
    • LG-PostgreSQL
    • LG-ORACLE_BBED
    • LG-ORACLE
    • LG-Elasticsearch(ES)+ELK
    • Oracle-19C-OCP
    • WERN_ORACLE培训
    • redis数据库
    • Nginx培训学习系列
  • 其他
    • 外研英语4年级下册-听力
    • 影视系列
    • 如何使用iTunes软件通过抓包下载旧版本的ios的app
Oracle数据库恢复专家团队:TEL:18562510581(微信同号);QQ:284833194;QQ群:496333360
天高任鸟飞
  1. 首页
  2. Oracle基础知识
  3. Oracle核心经典分析
  4. 正文

ORACLE—redo与undo—核心知识点1——insert/update/commit/rollback前后都发生了什么,undo和redo是怎么工作的?

2021年6月9日 1328点热度 1人点赞 0条评论

目录

  • 一、“延迟段”创建表
  • 二、redo 重做日志的触发条件:
  • 三、insert数据
    • 1、insert之后的系统状态【此时重做日志的触发条件未被触发】
    • 2、insert之后的系统状态【此时重做日志的触发条件被触发】
  • 四、Update数据【delete与update非常类似】
  • 五、应用回滚事务--假想场景
    • 1、应用回滚事务流程
    • 2、需要注意的是:
  • 六、commit流程
  • 七、COMMIT需要做的事情是有哪些?
    • 1、commit提交,是多次小提交,还是一次大提交?
    • 2、commit一次还是多次的案例
    • 3、commit的真实的情况
    • 4、commit的相应时间不会随着事物的大小而改变
    • 5、commit之前,数据库做了哪些工作?
    • 6、执行commit时,只剩下如下的工作:
  • 八、rollback做什么?
    • 1、commit/rollback之前,数据库做了哪些工作?
    • 2、ROLLback 时,还需要做如下工作:

ORACLE—图灵小队—核心知识点1——undo、redo、insert/update/commit/rollback

一、“延迟段”创建表

11gR2之后,会默认使用延迟段方式创建,表创建了,但并未分配段,只有在第一条数据插入时才会创建。

create table t(x int) segment creation deferred  ----延迟段创建

create table t(x int) segment creation immediate----立即创建段

可以通过此语句查看:

select extent_id, bytes, blocks
from user_extents
where segment_name = 'T'
order by extent_id;

二、redo 重做日志的触发条件:

  --用户提交(commit)
  --有 1/3 重做日志缓冲区未被写入磁盘(磁盘是指redo01.log等)
  --有大于1m 的重做日志缓冲区未被写入磁盘
  --3 秒超时
  --dbwr 需要写入的数据的 scn 大于 lgwr 记录的 scn,dbwr 触发 lgwr 写入。

三、insert数据

1、insert之后的系统状态【此时重做日志的触发条件未被触发】

插入数据后,undo块(存放索引,表修改前的数据,又因为是插入数据,所以当前行插入前并没有数据记录,比update后存放的数据少)、索引块、表数据块都会先进入块缓冲区缓存,所有这些都会写入重做日志redo log缓冲区,进行数据保护,等重做日志的触发条件触发后,才会写入redo log文件。

上述情况,

(1)如果系统崩溃,即使SGA被清空,因为用户并没有提交数据( 用户commit后,肯定会写入redo log中(这是redolog的触发条件),即使此时没有写入数据data文件中,只要写入redo log就能恢复,启动后把数据写入到数据文件中。如果用户不进行commit,达到重做日志触发条件,也会写入redolog中。但对于用户而言,用户commit的,才是他最需要的。如果用户没有commit的但已经写入到redolog中的,实例启动后,先redo前滚到数据文件中,再通过undo回滚到没有commit的状态,也不影响真实数据),我们不需要使用这些undo和redo信息进行实例恢复。

(2)如果缓冲区缓存满了或其他触发redo log的条件(见2)达到了,LGWR会将redlog缓冲区的信息刷到磁盘上去(redo01.log,redo02.log等),保存了undo、索引,表的信息

2、insert之后的系统状态【此时重做日志的触发条件被触发】

redo log缓冲区的数据,因达到触发条件,而被写入到磁盘中

四、Update数据【delete与update非常类似】

update和insert差不多,唯一区别就是,update之前,当前行是有数据的,undo需要存放update之前的数据信息。而insert动作之前,表中当前行是空的,undo块只需要存放少量空数据标记。

解析:

如果redo的黑块,表示上述三中insert插入的数据,此时实例崩溃了,重启实例做如下步骤:

1、系统崩溃时,系统所处的状态是:insert的语句已经写入到在线重做日志中(这部分redo也会包含insert语句相关的undo段)。

2、而此时Update语句的redo还没来得及写入到磁盘中,而依旧在日志缓冲区中(在系统崩溃时这部分redo会丢失)。这没问题,我们的事务还没有提交(commit),而磁盘上的数据状态就是update之前的状态。

3、此时insert语句的内容已经在系统崩溃之前写到redolog(磁盘)上了,此时oracle会利用这些redo信息“前滚”插入到数据文件,当前滚结束时,系统的状态将于上图9-1非常类似,缓冲区缓存里面有修改过的undo块(用于回滚未提交的insert)、表块(insert后的状态)及索引块(insert后的状态)。

4、由于这是oracle正处于自动的实例恢复过程中,它会回滚所有未提交的事务,包括我们刚才的那个insert语句的事务。

5、当oracle回滚我们的这个未提交的insert时,它会首先取到刚才提到的前滚过程中构建的undo数据,然后将这部分undo应用到数据以及索引块,从而使得数据和索引块“恢复”为insert发生前的样子。

6、现在一切都恢复到了insert之前的状态,不过磁盘上的数据块可能是inert之前,也可能是insert之后的状态(这取决于在崩溃前是否已经将块刷新(flush buffer_cache)输出)。

  (1)如果磁盘上的块是insert之后的状态,那么当下次这个块从缓冲区缓存刷到磁盘时,数据文件就会反映出insert已撤销状态。

  (2)如果磁盘上的块insert之前的状态,那就不用去管它-----这些块以后肯定还会被覆盖。

五、应用回滚事务--假想场景

1、应用回滚事务流程

当应用发出ROLLBACK命令时,Oracle会去查找这个事务的undo信息,它可能在缓存的undo段的块中(通常是这样),也可能已经刷新输出到磁盘上(对于非常大的事务,就往往是这种情况)。接下来Oracle会把undo信息应用到缓冲区缓存中的数据和索引块上,或者倘若数据和索引块已经不在缓存中,则要从磁盘将数据和索引块读入缓存,再对其应用undo。这些块会恢复为其原来的状态,并在以后会刷新输出到数据文件。

2、需要注意的是:

(1)回滚过程从不会涉及重做日志,只有恢复和归档是才会读取重做日志。这对于调优意义重大:

(2)意义重大:重做日志是用来写的,不是用来读的,oracle 不会在正常的处理中读取重做日志。

(3)只要你有足够的设备,使得ARCn读文件时,LGWR能写到另一个不同的设备,就不存在重做日志竞争。

(4)许多其他的数据库(非oracle)都把日志文件处理为“事务日志”,这些数据库没有把redo和undo分开。对于这些系统,回滚可能是灾难性的,回滚进程必须读取日志,而日志写入器也可能会在同时写这个日志,这就像系统中最薄弱的环节引入了竞争。

(5)oracle的目标是可以顺序地写日志,而且在写日志时别人不会读日志。

六、commit流程

(1)当事务进行提交时,oracle会把重做日志缓冲区刷新(flush buffer_cache)输出到磁盘(redo log),如图(9-4)

(2)此时已修改的块放在缓冲区缓存中,可能有一些块已经被刷新输出到磁盘上(flush buffer_cache,即使不提交,缓存块也会在一定条件下写入到数据文件data中。提交了也不一定写入到data中)。

(3)重做这个事务所需的全部redo都安全地存放在磁盘上,现在我们所做的修改已经具有持久性了。

(4)此时如果我们从数据文件直接读取数据,可能会看到块还是事务发生前的样子(通过dump出当前事务的文件和块,可以看到数据文件还是update前的数据),因为很有可能DBWn还没有(从缓冲区缓存)刷出这些块。这没有关系。

(5)如果出现宕机,那么在实例恢复的过程中,数据库可以利用重做日志文件来讲这些块更新为最新状态。

(6)数据库会一直保留着undo信息,除非undo段回绕并重用这些undo块。

(7)oracle会使用这些undo信息为需要这些对对象的会话提供一致性读。

七、COMMIT需要做的事情是有哪些?

1、commit提交,是多次小提交,还是一次大提交?

你可能认为,一个事务越大(换句话说,它影响的数据越多),commit需要的时间就越长。不是这样的,不论事务有多大,commit的相应时间一般都很“稳定“,这是因为commit并没有太多的工作去做,不过他所做的确实至关重要。

2、commit一次还是多次的案例

假设我们commit一行的update需要x个时间,那我们提交1000行的update基本也需要x个时间。如果我们commit一个1行update,执行1000次,那么需要的时间就是1000*X个时间。

3、commit的真实的情况

提交越多,耗时越久(.net,C,COBOL等),但pl/sql除外,为什么呢?为什么呢?

PL/SQL也是一种程序语言,叫做过程化SQL语言(Procedural Language/SQL)。PL/SQL是Oracle数据库对SQL语句的扩展。在普通SQL语句的使用上增加了编程语言的特点,所以PL/SQL把数据操作和查询语句组织在PL/SQL代码的过程性单元中,通过逻辑判断、循环等操作实现复杂的功能或者计算。

4、commit的相应时间不会随着事物的大小而改变

这是因为在数据库执行commit之前,困难的工作都已经做了。99%的工作都已经完成。

5、commit之前,数据库做了哪些工作?

(1)已经在SGA中生成了undo块;

(2)已经在SGA中生成了已修改数据块;

(3)已经在SGA中生成了对应前两项的redo缓存;

(4)如果前三项比较大且耗时较长,那这三项中的某些数据可能已经被刷新到磁盘;(通过update后,不提交,找到这个v$transaction中的文件号和块号,dump出,可以找到这个数据块的记录已经更新最新数据了,大约需要5分钟左右会自动刷新)

(5)已经得到了所需的全部锁。

6、执行commit时,只剩下如下的工作:

(1)为事务生成一个SCN

(2)LGWR将所有未写入磁盘的重做日志条目写至磁盘,并把SCN记录到在线重做日志文件中。

其中这里是最耗时的,但因为LGWR一致不停地将重做日志换成弄去的内容刷到磁盘上去。在你修改数据的过程中,redo不会一致在日志缓冲区中不断积累,LGWR会在你修改的同时以增量方式将日志缓冲区的内容写到磁盘上,这就避免了commit需要等待很长时间来一次性刷新输出到所有的redo。

(3)v$lock中会记录我这我们的会话持有的锁,这些锁都会被释放,而排队等待这些锁的会话都会被唤醒,从而可以继续完成它们的工作。

(4)如果事务修改的某些块还在缓冲区缓存中,oracle就会以一种快速的模式访问并“清理”。

八、rollback做什么?

我们将上述commit改为rollback,可能会得到完全不同的结构。回滚时间一定是和修正数据量成正比的。

1、commit/rollback之前,数据库做了哪些工作?

(1)已经在SGA中生成了undo块;

(2)已经在SGA中生成了已修改数据块;

(3)已经在SGA中生成了对应前两项的redo缓存;

(4)如果前三项比较大且耗时较长,那这三项中的某些数据可能已经被刷新到磁盘;(通过update后,不提交,找到这个v$transaction中的文件号和块号,dump出,可以找到这个数据块的记录已经更新最新数据了,大约需要5分钟左右会自动刷新)

(5)已经得到了所需的全部锁。

2、ROLLback 时,还需要做如下工作:

(1)撤销所有修改。Oracle数据库会读取undo段,然后将undo数据应用到数据块一撤销我们的修改,并将相应的undo条目标记为已应用。如果先前插入了一行,rollback会将其删除;如果更新了一行,回滚就会取消更新;如果删除了一行,回滚将把它再次插入。

(2)会话持有的所有锁,都将被释放,如果有会话在排队等待我们的持有的锁,就会被唤醒。

相比之下,commit只是将重做日志缓冲区中剩余的数据刷新输出到磁盘,它比rollback的工作量要小的多。

所以除非不得已,否则不要轻易回滚。

 

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2023年11月18日

admin

这个人很懒,什么都没留下

打赏 点赞
下一篇 >

COPYRIGHT © 2022 拓扑园. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

鲁ICP备2021020523号

鲁ICP备2021020523号