Oracle体系结构初探:聊聊REDO

上一篇文章写了undo(文章链接:聊聊UNDO),这篇和大家一起聊聊redo。redo如果按照我的傻瓜翻译,意为再次去做、重新去做。Oracle官方对于redo的描述是:记录对数据所做的所有更改,包括未提交和已提交的更改;通过REDO来保证数据库的事务可以被重演,从而使得在故障之后,数据可以被恢复。

事务重演,这个名词稍微抽象一点点;我个人在抽象事务理解上比较愚笨,最开始在学习的时候花了不少功夫才理解这个名词。所以也想在这里举个例子和大家分享下我的拙见:

2024-04-18 00:00:00,我启动了Oracle数据库实例ORCL;

从此刻开始,ORCL对应的应用系统开始正常运行,开始向ORCL中增删改查数据;

2024-04-18 18:05:20,ORCL所在服务器突然意外关机了;

在关机的此时此刻有个INSERT操作,已经提交,但数据还未来得及写入磁盘;

2024-04-18 18:13:14,服务器恢复,开始启动ORCL数据库实例(此时的这个操作,其实应该叫做恢复ORCL实例);但是关机时提交的INSERT数据并没有写入磁盘,这不就造成了数据丢失嘛!Oracle多聪明,它此时会根据redo日志(online redo log)里的内容,将INSERT操作重新执行一遍,这就避免了此问题。

上面将INSERT操作重新执行一遍的过程,就是事务重演。

上面的例子,其实还有个专业的叫法:前滚;即已提交未写入的数据再次写入。

前滚是发生在Oracle实例恢复时的一个步骤。

那么正好在此处简单描述下实例恢复的过程:Oracle实例崩溃,进行实例恢复;① 先发生前滚,② 再打开数据库,③然后发生回滚。

以上是实例恢复的三个阶段,可以发现除了redo以外,undo也参与了实例恢复,因为发生了回滚。这也是在上一篇文章 《聊聊UNDO》中没有提到的UNDO的一个功能。

下面开始和大家分享下redo相关的一些基本知识内容,先看目录。

目录

redo相关组件

redo日志循环写

归档模式 

非归档模式 

redo日志状态

redo日志切换

redo日志操作


redo相关组件

在数据库中,redo的功能主要通过3个组件来实现:Redo Log Buffer、LGWR后台进程和Redo Log File。下面分别对这3个组件进行介绍。

  • Redo Log Buffer

Redo Log Buffer位于SGA中,是一块循环使用的内存区域,用来保存数据库变更的相关信息。这些信息以Redo Entries(重做条目)形式存储。

Redo Entries包含重构、重做数据库变更的重要信息(包括INSERT、UPDATE、DELETE、CREATE、ALTER或者DROP等)。而这些Redo Entries内容是被Oracle数据库进程从PGA复制到SGA中的Redo Log Buffer中的;多提一句的是SQL的语义解析,语法解析,执行计划都是在PGA中进行的,所以我们也就能推测到Redo Entries的信息格式大概是什么了。

Redo Entries主要是scn、时间戳、sql_redo等信息,这些信息可以通过Oracle的LogMiner工具去分析查看(配合v$logmnr_contents视图)。其中sql_redo就是产生redo的具体sql内容。

  • 后台进程LGWR

LGWR的作用是循环把Redo Log Buffer中的内容写出到Redo Log File中。当满足以下条件时,会触发LGWR进程:

  1. 事务提交时
  2. 每3秒钟
  3. 彻底关机前
  4. 在DBWN写入之前
  • Redo Log Files

重做日志文件,以组(group)出现。可以通过v$logfile查询相关日志文件信息。

select * from v$logfile

在这里重做日志文件又可以分为:ONLINE REDO LOG(在线重做日志)和 ARCHIVE REDO LOG(归档重做日志) 

ONLINE REDO LOG

Oracle以SQL脚本的形式实时记录数据库的数据更新,换句话说,按特定的格式实时保存已执行的SQL脚本到在线日志文件中,这个格式其实就是前文提到Redo Entries。

ARCHIVE REDO LOG

归档重做日志,简称归档日志,指当条件满足时,Oracle将在线重做日志以文件形式保存到硬盘(持久化)

从实际情况来看 ARCHIVE REDO LOG 其实就是 ONLINE REDO LOG 的备份。

redo日志循环写

那么ONLINE REDO LOG(在线重做日志)和 ARCHIVE REDO LOG(归档重做日志) 是如何参与Oracle的工作的呢?

先不急,我们再进一步探究下Redo Log File的细节信息:

Ⅰ:每个Oracle数据库都至少有2个Online重做日志组,每个组中至少有1个重做日志文件,这些Online重做日志组以循环方式使用。

Ⅱ:每组内的日志文件的内容完全相同,且保存在不同的位置,用于磁盘日志镜像,以做多次备份提高安全性。

Ⅲ: 我们是可以根据实际情况自定义添加、修改、删除日志组和日志文件的。

Ⅳ:在默认情况下,Oracle只有1个重做日志组处于活动状态;

数据库在开启归档模式状态下 和 非归档模式下的重做日志工作方式是不一样的,我们先来一起看下归档模式下的重做日志是如何工作的。

归档模式 

假设Oracle数据库有3个日志组:1#、2#、3#。

LGWR进程循环地向 1#日志组的 ONLINE REDO LOG 中写入特定格式的SQL脚本;

当1#日志组的 ONLINE REDO LOG 写满时,则将在线日志归档到硬盘,成为 ARCHIVE REDO LOG;

当1#日志组的 ONLINE REDO LOG 写满后,Oracle切换到2#日志组,开始向ONLINE REDO LOG写入特定格式的SQL脚本;

 如果1#日志组的 ARCHIVE REDO LOG 已经写完(归档结束),且2# 日志组ONLINE REDO LOG已经写满,那么2#日志组开始归档

⑤ 2# 日志组ONLINE REDO LOG已经写满,则切换至 3# 日志组,开始向ONLINE REDO LOG写入特定格式的SQL脚本;

 如果2#日志组的 ARCHIVE REDO LOG 已经写完(归档结束),且3# 日志组ONLINE REDO LOG已经写满,那么3#日志组开始归档

3# 日志组ONLINE REDO LOG已经写满,则重新切换至 1# 日志组,开始向ONLINE REDO LOG写入特定格式的SQL脚本;

循环以上过程

如果我们细心一点,可以发现一个细节:如果服务器磁盘性能差,归档速度慢,那么重做日志组切换就会出现问题。比如上述循环过程中,3#日志组的ONLINE REDO LOG写满后,1#日志组还在归档,那么此时是不会切换到1#日志组的,只能使用日志缓冲区,等待归档完毕之后才能覆盖写入。

非归档模式 

至于非归档模式状态下的redo日志循环写流程,就比较简单了,因为没有归档过程,如下图所示。还是假设有3个日志组:1#、2#、3#。只不过这次流程十分精简:

 LGWR进程循环地向 1#日志组的 ONLINE REDO LOG 中写入特定格式的SQL脚本;

② 1#日志组写满后,切换至2#日志组,LGWR进程循环地向 2#日志组的 ONLINE REDO LOG 中写入特定格式的SQL脚本;

2#日志组写满后,切换至3#日志组,LGWR进程循环地向 3#日志组的 ONLINE REDO LOG 中写入特定格式的SQL脚本;

3#日志组写满后,重新切换至1#日志组,LGWR进程循环地向 1#日志组的 ONLINE REDO LOG 中写入特定格式的SQL脚本;

循环以上过程

非归档模式下redo日志循环写

 

redo日志状态

关于redo日志状态,需要分成两块去讲。一块是redo日志组的状态,一块是redo日志文件的状态。

  • redo日志组状态

可以通过v$log视图查询redo日志组状态。

select group#,bytes,status from v$log;
SQL> select group#,bytes,status from v$log;

    GROUP#      BYTES STATUS
---------- ---------- ----------------
         1  209715200 INACTIVE
         2  209715200 CURRENT
         3  209715200 INACTIVE

通过上述输出结果可以看到这里已经有两种状态为INACTIVE和CURRENT,那么现在把REDO LOG组所有的状态都列出来。并给出相应解释:

Ⅰ:INACTIVE 

实例恢复不再需要联机重做日志组,它可能已经归档也可能未归档。

Ⅱ:ACTIVE

联机重做日志组是活动的,但是并非当前联机重做日志组,实例崩溃恢复需要该状态的日志,它可能用于块恢复,它可能已经归档也可能未归档。

Ⅲ:CURRENT

当前的联机重做日志组,这意味着该联机重做日志组是活动的。

Ⅳ:UNUSED

从未对联机重做日志组进行写入,这种状态的日志文件要么是刚增加的,要么是当日志不是current redo log时RESETLOGS操作后的状态。

Ⅴ:CLEARING

在ALTER DATABASE CLEAR LOGFILE 命令后正在将该日志重建为一个空日志,日志清除后其状态更改为UNUSED。

Ⅵ:CLEARING_CURRENT

正在清除当前日志文件中的已关闭线程,如果切换时发生某些故障,如写入新日志标题时的I/O错误,则该日志可以停留在该状态。

  • redo日志文件状态

可以通过v$logfile视图查询redo日志文件状态。

select group#,member,status from v$logfile;
SQL> select group#,member,status from v$logfile;

    GROUP# MEMBER                                   STATUS
---------- ---------------------------------------- -------
         3 /u01/app/oracle/oradata/ORCL/redo03.log
         2 /u01/app/oracle/oradata/ORCL/redo02.log
         1 /u01/app/oracle/oradata/ORCL/redo01.log

通过上述输出结果,可以看到这里STATUS(状态)列下并无数据,但实际上现在这个列中的值为NULL,那么我们把REDO LOG文件所有的状态都列出来。并给出相应解释: 

Ⅰ:INVALID

该文件不可访问

Ⅱ:STALE

该文件内容不完全,例如正在添加一个日志文件成员

Ⅲ:DELETED

该文件已不再使用

Ⅳ:NULL

该文件正在使用中

redo日志切换

redo日志切换,其实指的是redo日志组切换。redo日志组可以用两种方法去切换。但推荐的是用正常方式去切换。

  • 正常切换
alter system switch logfile;

切换例子如下 

 

  • 用发生检查点的方式去切换 
alter system checkpoint;

redo日志操作

  •  添加组成员

假如需要给1#日志组添加组成员;

先通过 select member from v$logfile;查询出对应redo日志文件路径。

再替换到下列语句中。

ALTER DATABASE
ADD LOGFILE MEMBER '/u01/app/oracle/oradata/ORCL/redo01.rdo'
TO GROUP 1

添加组成员有2个需要注意的地方:

Ⅰ:新增组成员不需要指定大小,因为每个组内的成员日志内容是一样的,所以大小和已存在的组成员一致。

Ⅱ:当组成员刚刚被添加时,它的日志文件状态是INVALID不可访问状态,如下图。

 那咋办嘞?

这时候就用到上文叙述过的redo日志组切换操作,操作结果如下图所示。

 

  • 删除组成员

删除语法很简单,如下所示,删除之前添加的1#日志组新成员redo01.rdo。

ALTER DATABASE DROP LOGFILE MEMBER '/u01/app/oracle/oradata/ORCL/redo01.rdo';

删除组成员有两个需要注意的地方:

Ⅰ:上述的删除语法只是在控制文件中,将日志组成员删除了;未真正在物理磁盘上将redo01.rdo文件删除;所以需要手动去对应路径下删除对应的redo01.rdo文件。

Ⅱ: 不能删除CURRENT状态下的日志组成员。

  • 添加组

还是和添加组成员一样,先找到其他组成员的存储路径,再替换到下面的代码中。

新建的组,可以指定组成员默认大小是多少。如下代码,指定的是组成员大小是200M。

ALTER DATABASE ADD LOGFILE GROUP 4 ('/u01/app/oracle/oradata/ORCL/redo04.log') 
SIZE 200M

添加组有2个需要注意的点:

Ⅰ:无法改变已存在的日志组成员大小;

Ⅱ:刚创建的日志组状态是UNUSED的,也可以进行手动切换日志组,进行状态的调整。


以上是关于redo的基本知识内容,按我自己的拙见是比较全面了。但redo与备份和恢复的关系没有提到太多。因为觉得内容太多,一章说完比较困难,后面再补吧。


另外也记录下一件小事:昨天,我对象发现了我头上长了一根白头发;这是我第一次长白头发,我真的要开始变老了,欸。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/560827.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Electron+Vue3整合 - 开发时状态整合

说明 本文介绍一下 Electron Vue3 的整合的基本操作。实现的效果是 : 1、一个正常的Vue3项目; 2、整合加入 Electron 框架 :开发时 Electron 加载的是开发的vue项目;步骤一:创建vue3项目 常规操作,不再赘…

启动 UE4编辑器报 加载 Plugin 失败

启动 UE4编辑器报 加载 Plugin 失败,报如下错误: Plugin ‘SteamVR’ failer to load because module ‘SteamVR’ could not be found. Please ensure the plugin is properly installed, otherwise consider disabling the plugin for this project. …

yolov5-6.0调测记录

直接运行yolov5-6.0/detect.py,输出如下: image 1/2 C:\Users\dun\Downloads\yolov5-6.0\data\images\bus.jpg: 640x480 4 persons, 1 bus, Done. (0.216s) image 2/2 C:\Users\dun\Downloads\yolov5-6.0\data\images\zidane.jpg: 384x640 2 persons, 2…

单链表的简单应用

目录 一、顺序表的问题及思考 二、链表的概念及结构 三、单链表的实现 3.1 增 3.1.1 尾插 3.1.2 头插 3.1.3 指定位置前插入 3.1.4 指定位置后插入 3.2 删 3.2.1 尾删 3.2.2 头删 3.2.3 指定位置删除 3.2.4 指定位置后删除 3.2.5 链表的销毁 3.3 查 3.4 改 四…

【Godot4自学手册】第三十九节利用shader(着色器)给游戏添加一层雾气效果

今天,主要是利用shader给游戏给地宫场景添加一层雾气效果,增加一下气氛,先看一下效果: 一、新建ParallaxBackground根节点 新建场景,根节点选择ParallaxBackground,命名为Fog,然后将该场景保…

什么是AIoT?

什么是AIoT? AIoT,即人工智能物联网,是一种将人工智能(AI)技术与物联网(IoT)相结合的新型应用形态。它不仅实现了设备之间的互联互通,还赋予了它们更智能化的特性。AIoT的核心在于通过AI的数据…

prometheus+grafana可视化监控

prometheus监控 一、用二进制安装 1、安装Prometheus 打开官方网址:https://prometheus.io/download/ wget https://github.com/prometheus/prometheus/releases/download/v2.45.4/prometheus-2.45.4.linux-amd64.tar.gz下载完成后解压一下安装包 tar vxf prometheus-2.45.…

解锁棋盘之谜:探索N皇后问题的全方位解决策略【python 力扣51题】

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。 会一些的技术:数据分析、算法、SQL、大数据相关、python 欢迎加入社区:码上找工作 作者专栏每日更新: LeetCode解锁1000题: 打怪升级之旅 python数据分析…

软考138-上午题-【软件工程】-软件评审

一、软件评审 通常,把“质量”理解为“用户满意程度”。为了使得用户满意,有以下两个必要条件: (1) 设计的规格说明书符合用户的要求,这称为设计质量。 (2) 程序按照设计规格说明所规定的情况正确执行,这称为程序质…

Docker安装教程,什么系统都有

下载Docker 如果你的系统是图形界面的,比如windows、mac、ubuntu等,到 Docker 官网下载 Docker Desktop。 官网链接: https://www.docker.com/products/docker-desktop/ 根据你的系统选择对应的安装包,然后下载,是不是特别简单&a…

Git TortoiseGit 安装使用详细教程

前言 Git 是一个免费的开源分布式版本控制系统,是用来保存工程源代码历史状态的命令行工具,旨在处理从小型到非常大型的项目,速度快、效率高。《请查阅Git详细说明》。TortoiseGit 是 Git 的 Windows Shell 界面工具,基于 Tortoi…

改进前后端交互实例

前后端交互实例(javaweb05)-CSDN博客 在这之前我假设大家都已经学完了IOC和DI 不明白的这里我也解释一下,首先是两个概念 1.控制反转:对象的创建控制权由程序自身转到外部(容器) 2.依赖注入:容器为程序提供运行时所依赖的资源 Bean对象:IOC容器中创建,关联的对象,称之为be…

【wpf】ObservableCollection 跨线程报错问题

背景 ObservableCollection 我们之前介绍过他和List的区别。ObservableCollection 的好处在于,当集合发生变化时,能发送通知通知界面发生相应的更改。但是ObservableCollection 有个弊端。无法在非UI线程中访问。 要么就是通知失效了,要么就…

从0到1实现RPC | 接入Apollo配置中心

一、代码实现 添加依赖 添加apollo客户端的依赖和spring配置相关依赖 添加监听器 通过实现ApplicationContextAware接口,获取Spring上下文。 使用ApolloConfigChangeListener注解监听命名空间rpc-demo-provider.yaml和默认的application.properties。 监听逻辑…

前端页面助手 (vue)

快速开发页面(图形化开发页面) 自主编辑 然后自己也可以修改属性 最后导出页面即可 github地址 ;https://github.com/opentiny/tiny-engine

虹科Pico汽车示波器 | 免拆诊断案例 | 2016款保时捷911 GT3 RS车发动机异响

一、故障现象 一辆2016款保时捷911 GT3 RS车,搭载4.0 L水平对置发动机(型号为MA176),累计行驶里程约为4.2万km。车主反映,1星期前上过赛道,现在发动机有“哒哒”异响。 二、故障诊断 接车后试车&#xff…

C++语言·类和对象(下)

1. 初始化列表 我们回忆上节写的MyQueue类,其中有两个栈类和一个int类型,栈类因为其特殊性,要开空间,所以我们必须手搓Stack类的构造函数。但是正常来说MyQueue自动生成的构造函数会调用自定义类型的默认构造函数,也就…

Proxy 代理

意图 为其它对象提供一种代理以控制这个对象的访问。 结构 Proxy保存一个引用使得代理可以访问实体;提供一个与Subject的接口相同的接口,使代理可以用来替代实体;控制实体的存取,并可能负责创建和删除它;其他功能依赖…

【leetcode面试经典150题】63. 删除链表的倒数第 N 个结点(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…

现货白银保证金交易要先分析趋势

现货白银是保证金交易品种,买卖过程中可能会涉及数十倍的资金杠杆,所以它对投资者的分析水平和交易水平的要求都比较高,所以在进入这个市场之前,投资者需要先学习一些基本的分析方法,当中可以分为基本面和技术面两大流…