目录
LLL的数据库培训—第二部分—Oracle基础知识培训—第18讲—还原日志(undo log)文件之一概念与管理
引子:
如果我们学习过数据库管理系统原理之类的课程可能还有印象,当数据库管理系统对数据库中一行数据进行写操作时,需将该行数据用排他锁锁上,除了正在进行操作的进程之外,其他的任何进程(用户)是不能访问上了排他锁的数据行的。
虽然从理论上说这样可能是完美的,但是在实际的商业环境中却带来了效率问题。设想一下,如果在一个生产数据库中有人修改了1000行数据,而此人又有一个坏毛病,就是从不提交或回滚自己所做的任何事务,进一步假设这1000行数据是公司经常使用的数据,读者可以想象会产生什么样的后果。
而 Oracle使用了完全不同的解决方案。
在 Oracle系统中当有一个进程正在写某一行数据时,其他的进程可以读这行数据但不能进行写操作,此时其他进程读的是写之前的数据, Oracle是通过在所有的DML操作之前将原来的数据复制到还原段( Oracle9i之前称为回滚段)上来实现这一功能的。
在本章的各节中将详细地描述还原数据的目的,如何实现自动的还原数据管理,如何创建和配置还原数据表空间,以及如何获得还原段的信息等。
一、undo数据(undo 段)的概念
1、还原数据的管理方法
尽管回滚段的使用巧妙地解决了当一个进程写某一行数据时其他的进程不能读该行数据的难题,但是在 Oracle9i之前的版本中回滚段(回滚数据)的管理一直让许多初学者望而生畏。因为所有回滚段的管理都是手工操作的。
Oracle9i引入了一种自动管理这些数据的方法。在 Oracle9i或以后的版本中提供了两种方法来管理还原数据。
(1)自动的还原数据管理: Oracle服务器自动地管理还原段的创建、分配和优化等。
(2)手动的还原数据管理:所有的还原段的创建、分新值配和优化等都是手工管理的。
这里还原(undo)一词在 Oracle9i之前的版本中被称为回滚(rollback),下图所示是一个 Oracle进行修改操作的示意图。
在 Oracle数据库中,当某个进程修改(insert/update/delete)数据时, Oracle首先将它的原始值(还原数据)存入一个还原段中。
一个事务只能将它的全部还原数据存放在同一个还原段中。
但是多个并行的事务可以写一个还原段。
每个还原段都有一个段头,在该段头中包含了一个事务表,该表中存放着有关使用这一还原段的当前事务信息。
2、Oracle使用还原段的作用(目的)
从下图可以看出, Oracle使用还原段共有3个作用,分别是事务回滚、事务恢复和保证数据的读一致性。
(1)事务回滚:
当一个用户发出了一些DML语句之后,改了主意,使用了 ROLLBACK语句回滚了他所做的事务,此时 Oracle服务器就会将还原段中的原始数据回写到原来的数据行中。
(2)事务恢复:
如果当事务正在进行期间实例崩溃了,则还原段当数据库再次打开时, Oracle服务器就要还原(回滚)所有没有提交的变化。 这种还原(回滚)就是事务恢复的一部分。 要使恢复真正成为可能,写到还原段上的变化也要受到联机重做日志文件的保护。(此处可以这样理解,undo段的变化也要记录到redo log中,redo log也包含了undo表空间的变化)
(3)保证数据的读一致性:
当事务在进行期间,数据库中的其他用户不应看到任何这些事务所做的没有提交的变化。
另外,一个语句不应该看到任何在该语句开始执行后所作的变化。换句话说,一个语句在执行期间所看到的数据是静止的。
(4)闪回功能
在新的版本中,11g及之后,可以用于Oracle闪回查询,闪回交易,闪回表操作。
此处实验:
进行两个session对比,一个进行插入操作,不提交;登录另一个session查询是否有新数据。提交后,再查看,是否已经可以查询到新数据。
3、undo的前映像 原理
说到 undo 保存的是数据库中被修改数据的前映像时,有人可能会认为 oracle 会在数据发生修改的时候将整个数据块复制到回滚段中,然后在回滚的时候再拷贝回来。
而实际上不是这样的,这里所说的前映像只是数据的前映像, 而不是数据块的,这个要明确。
一个数据块在发生回滚之后与修改之前并不会是在物理上一样,只能说是逻辑上一样。
要证明这点的最直接的方法也许就是将 undo块的内容转储(dump)出来看看,但是阅读转储数据是个累人的活儿,实际上我们还是可以通过其它的方法来进行验证的。
4、前映像,又叫前镜像:
- 当某个进程更改了数据库中的数据时,oracle db 会保存旧值(还原数据),按数据修改前的原样存储数据。
- 通过捕获还原数据可以回退未提交的数据,还原数据用于支持读取一致性和闪回查询。
- 还原还可用于“倒回”(闪回)事务处理和表。
- 如果事务处理失败,则选择最安全的行为,即让 oracle db 撤销用户做出的所有更改,从而还原原始数据。
5、undo 分为自动 undo 和手动 undo
如果设为 auto, 就使用 undo 表空间,这时必须要指定一个 undo 表空间。
如果设为 manual,系统启动后使用 rollback segment 方式存储 undo 信息。
如果没有有效的可用的 undo 表空间或者是回滚段,系统使用 system rollback segment。
6、undo段的类型
可能是为了管理和维护的方便, Oracle数据库系统中的还原段分别具有以下不同的类型:
(1)系统(system)还原段:
仅为系统表空间中的对象变化所用。它是在数据库创建时在系统表空间中创建的系统还原段既可以存在并工作在自动模式下,也可以存在并工作在手动模式下
(2)非系统(non--system)还原段
为其他表空间中对象的变化所使用。当一个数据库具有多个表空间时就至少需要一个手动的非系统还原段或一个自动管理的还原表空间
非系统还原段又包括了自动管理的还原段和手动管理的还原段两种,其中手动管理的还原段分为私有和公有两类。
--自动模式:
需要一个还原表空间( tablespace), Oracle服务器将自动维护还原表空间中的还原数据。
--手动模式:
数据库管理员负责创建非系统还原段(回滚段),所有非系统表空间中对象的变化都将使用这样的非系统还原段。在 Oracle系统中包括了如下两类非系统还原段。
--私有还原段:为一个实例所用。 --公有还原段:为任何一个实例所用,通常是在 Oracle集群(real application clusters)中使用。
(3)延迟(deferred)还原段。
当一个表空间被设置为脱机时,如果需要,由 Oracle系统自动创建,延迟还原段被用来在该表空间重新设为联机时回滚事务。
当不需要他们时,系统会自动将他们删除。
7、自动还原数据管理的概念和配置
在 Oracle 9i之前,回滚段的管理和维护一直是令许多 Oracle从业人员“望而生畏”的事情。
(1)9i-10g:
数据库管理员为每个实例分配一个还原表空间,该表空间要有足够空间以应对该实例的工作负荷。
之后, Oracle服务器就将自动维护和管理还原表空间中的还原数据。
如果要 Oracle自动管理还原数据,数据库管理员就必须在初始化参数文件中配置以下两个参数UNDO_ MANAGEMENT和UNDO_TABLESPAC,而且还必须创建至少一个还原表空间。
其中:
UNDO MANAGEMENT:说明系统是使用自动(auto)还是手动(manual)模式。 UdTABLESPACE:说明系统使用哪个还原表空间。 可以在数据库的初始化参数文件中使用类似如下的参数设置,将还原数据的管理设为自动。 UNDO MANAGEMENT=AUTO UNDO_TABLESPACE=UNDOTBS1
(2)11g及之后默认,不需要管理员单独设置
SQL> show parameter undo
NAME TYPE VALUE ------------------- ----------- ------------------- undo_management string AUTO undo_retention integer 900 undo_tablespace string UNDOTBS1
二、undo表空间的创建和维护
1、两种方法创建还原表空间
(1)创建数据库时
创建数据库时,通过create database 命令中加入关于undo的子句即可。或者dbca时,选择定制化,在最后install的前一步进行自行设置 undo信息
(2)数据库创建之后,手动创建undo表空间
SQL>create undo tablespace undotbs2 datafiile '/oracle/oradat/undotbs2_1.dbf';
2、维护undo表空间
(1)增加数据文件
alter tablespace undotbs2 add datafile '/oracle/oradat/undotbs2_2.dbf' size 10m;
(2)更改数据文件
alter database datafile '/oracle/oradat/undotbs2_2.dbf' size 50m;
(3)查看当前undo表空间undotbs2的状态及数据文件
SQL> select file_name,tablespace_name from dba_data_files where tablespace_name like '%UNDO%';
3、undo表空间之间的切换
如果在数据库中有多个还原表空间,则可以从一个正在使用的还原表空间切换到另一个还原表空间。
但是 Oracle规定在任何时刻只能将一个还原表空间赋予数据库。
也就是说,在一个实例中可以有多个还原表空间存在,但是只能有一个为活动的。此时可以使用 ALTER SYSTEM命令来进行还原表空间之间的动态切换。
(1)查看正在使用的undo表空间
SQL> show parameter undo
NAME TYPE VALUE ------------------- ----------- ------------------- undo_management string AUTO undo_retention integer 900 undo_tablespace string UNDOTBS1
(2)切换undo表空间为undotbs2
SQL> alter system set undo_tablespace=undotbs2;
(3)查看当前使用的undo表空间
SQL> show parameter undo
NAME TYPE VALUE ------------------- ----------- ------------------- undo_management string AUTO undo_retention integer 900 undo_tablespace string UNDOTBS2
4、undo表空间的删除
当undo表空间没有在使用时才可以进行删除。所以先切换回undotbs1;
SQL> alter system set undo_tablespace=UNDOTBS1; SQL> drop tablespace undotbs2 including contents and datafiles;
5、undo表空间的rentention 参数和retention属性
此属性用于保留undo表空间数据的时间,默认时900s,即15分钟。
如果有一个报表查询需要1.5小时,如果默认undo表空间只保留15分钟,那么在1.5小时查询过程,可能会出现不一致现象。为了避免此问题,我们需要设置retention为2小时,并且在此期间要保证还原段的数据空间足够,时刻关注表空间资源大小。
(1)rentention参数查看与修改
--参数查看
SQL> show parameter undo
NAME TYPE VALUE ------------------- ----------- ------------------- undo_management string AUTO undo_retention integer 900 undo_tablespace string UNDOTBS1
--参数修改
SQL>alter system set undo_retention=1800;
(2)rentention 属性查看与修改
尽管设置了 UNDO RETENTION参数, Oracle默认也不能百分之百保证那些提交的数据保留到
设置的时间长度。因为如果有一个事务(transaction)需要还原段,可是现在已经没有空闲的还原段了(比如看空闲的还原段所在的数据文件已经满了,无法进行extend 了);Oracle还是会将某些已经提交但需要保留的数据覆盖掉以保证当前活动的事务。
如果要想保证提交的数据百分之百保留 UNDORETENTION参数所设定的时间,就需要修改当前原表空间的 RETENTION属性,该属性的默认值是 NOGUARANTEE,要将其修改成 GUARANTEE。
注意的是, RETENTION是表空间的一个属性而并不是初始化参数,因此这个属性只能通过SQL的命行语句来修改。以下通过一个实例来演示所需的具体操作步骤。
--属性查看
(undo表空间的rentention属性只有两个,noguarantee和guarantee。
SQL>select tablespace_name,retention,contents from dba_tablespaces;
--属性修改
SQL>alter tablespace undotbs1 retention guarantee;
三、还原数据的信息获取
为了更有效地控制还原数据, Oracle9i及之后的版本提供了一个获得还原数据统计(statistics)的工具,即数据字典v$undostat
1、获取还原数据信息
SQL> SELECT TO_CHAR(begin_time, 'HH:MM:SS') begin_time,TO_CHAR(end_time, 'HH:MM:ss') begin_time,undoblks,TXNCOUNT, MAXQUERYLEN from v$undostat;
2、参数解析
视图 v$undostat显示系统还原数据的统计信息。Oracle实例每10分钟收集一次统计信息并存放在该视图的某一行中。
在这个视图中一些常用的列包括:
BEGIN_TIME: 为日期型,标识时间间隔的开始。 END_TIME: 为日期型,标识时间间隔的结束。 UNDOBLKS: 为数据型,标识所消耗的还原数据块的总数。 TXNCOUNT: 为数据型,标识该时间段中事务的总数。 MAXQUERYLEN: 为数据型,标识该时间段中所执行的最长的查询(按秒数).
3、其他动态视图数据字典获取有关还原段信息
v$rollname v$rollstat v$session v$transaction
四、临时还原数据的管理(12c新特性)
1、临时表是一种特殊的表。
当需要对某一(可以是几个)表中的一批数据进行反复的操作时,通过为这批数据创建一个临时表可能会简化操作并且提高效率。
因为临时表是存放在临时表空间上的,而临时表空间的磁盘分配表是常驻内存的,另外在临时表上的变化也不直接产生重做日志记录(这可能是为临时表中的数据都来自其数据库中其他表因此即使临时表崩溃也不会丢失任何数据)。
不过在临时表上的一些需要进行还原操作的数据(如创建或维护索引)仍然需要重做日志操作,这无疑会影响 Oracle数据库管理系统的效率。
2、临时还原模式
通过进一步的分析可知:
在临时对象的存活期间,临时表上的还原数据对于保证读一致性和事务回滚是必须的,一旦在这个临时表的生命周期之外,这些还原数据就是多余的了。
因此,完全没有必要永久地保留这些重做信息。
经过了十多年的不懈努力, Oracle12c终于可以将临时表所产生的还原数据与普通的还原数据分开了,而将临时表上的还原数据直接存放在临时表空间上。
这种模式称之为临时还原模式。
3、临时还原数据管理的好处
一个临时还原段是会话一级的私有段。该临时还原段存储的是属于所对应会话的临时表上变化的还原信息。
现将引入临时还原数据管理的好处归纳如下:
(1)临时还原功能可以减少还原表空间上所存储的还原数据量这也使得DBA更容易确定undo retention参数; (2)临时还原功能可以减少重做日志的大小由于减少了重做数据,所以系统效率也就提高了; (3)临时还原功能使得在一个物理待机数据库(要有Oracle Active Data Guard选项)中在临时表上可以执行数据维护语言(DML)操作。
4、查看临时还原功能
5、如何开启临时还原功能
开启临时还原功能,既可以在会话一级,也可以在数据库一级开启临时还原功能。
(1)在会话一级开启临时还原功能的 Oacle SQL语句如下
alter session set temp_undoenabled true;
当使用以上命令在会话一级开启临时还原功能时只影响这个会话而其他的会话并不受影响。
(2)在数据库一级开启临时还原功能的 Oracle SQL语句则为
alter system set temp_undo_enabled true;
当使用以上命令在数据库一级开启临时还原功能时,所有现存的会话和新会话都受影响。下面通过
例子来演示如何开启和关闭数据库一级的临时还原功能。首先以 system用户登录数据,随后使用例8-46
的SQL*Plus命令显示当前数据库临时还原功能的配置。
SQL> show parameter temp undo
6、如何关闭临时还原功能
alter session set temp_undoenabled false; alter system set temp_undo_enabled false;
7、需要注意的
(1)当一个会话第一次使用临时对象时,系统会按照 temp_undo_enabled的当前值为该会话(余下的部
分)设置临时还原功能。因此,
如果临时还原功能被开启并且该会话使用一些临时对象,那么对于这会话是不能关闭临时还原功能的; 如果临时还原功能被关闭并且该会话使用一些临时对象,那么对于这一会话是不能开启临时还原功能的。
(2)如果要使用临时还原功能, Compatible初始化参数必须至少设置为12.1.0.0.0
(3)临时还原功能在一个物理待机数据库(要有Oracle Active Data Guard选项)上默认是开启的,并
且 temp_undo_enabled初始化参数的设置在一个物理待机数据库上是没有影响的。
8、临时还原统计信息的数据字典
为了更有效地控制临时还原数据,与数据字典 v$undostat类似, Oracle12c也提供了一个获得临时还原数据统计(statistics)信息的工具,即数据字典 v$tempundostat。
该数据字典与 vsundostat极为相似,可以通过使用SQL查询语句查询 v$tempundostat的方法来获取临时还原数据的统计信息。其方法与v$undostat极为相似,这也就是所谓的追踪临时还原数据的使用。
Oracle实例也是每10分钟收集一次临时还原数据的统计信息并存在 v$tempundostat视图中。