温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Oracle数据库的事务日志怎么理解

发布时间:2022-01-14 15:54:24 来源:亿速云 阅读:178 作者:iii 栏目:建站服务器

今天小编给大家分享一下Oracle数据库的事务日志怎么理解的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

redo

重做日志文件(redo log file)对Oracle数据库来说至关重要,它们是数据库的事务日志。Oracle维护着两类重做日志文件:

在线(online)重做日志文件和归档(archived)重做日志文件。这两类重做日志文件都用于恢复;其主要目的是,

万一实例失败或介质失败,它们就能派上用场。

如果数据库所在主机掉电,导致实例失败,Oracle会使用在线重做日志将系统恰好恢复到掉电之前的那个时间点。

如果磁盘驱动器出现故障(这是一个介质失败),Oracle会使用归档重做日志以及在线重做日志将该驱动器上的

数据备份恢复到适当的时间点。

归档重做日志文件实际上就是已填满的"旧"在线重做日志文件的副本。系统将日志文件填满时,

ARCH进程会在另一个位置建立在线重做日志文件的一个副本,也可以在本地和远程位置上建立多个另外的副本.

如果由于磁盘驱动器损坏或者其他物理故障而导致失败,就会用这些归档重做日志文件来执行介质恢复.

Oracle拿到这些归档重做日志文件,并把它们应用于数据文件的备份,使这些数据文件能与数据库的其余部分保持一至.

归档重做日志文件是数据库的事务历史。

测量redo

redo管理是数据库中的一个串行点.任何Oracle实例都有一个LGWR,最终所有事务都会归于LGWR,要求这个进程管理它们的redo,

并COMMIT其事务,LGWR工作越忙,系统就会越慢.通过查看一个操作会生成多少redo,并对一个问题的多种解决方法进行测试,

可以从中找出最佳的方法。

与redo有关的视图

V$MYSTAT,其中有会话的提交信息

V$STATNAME,这个视图能告诉我们V$MYSTAT中的每一行表示什么(查看的统计名)。

查询redo大小的语句

SELECT a.NAME,

b.VALUE cur_size_byte,

round(b.VALUE / 1024, 3) || 'KB' cur_size_kb

FROM v$statname a, v$mystat b

WHERE a.statistic# = b.statistic#

AND lower(a.NAME) LIKE '%' || lower('redo size') || '%'

数据库归档模式

数据库归档用来保存redo的日志文件副本,一般安装时默认未开启数据库的归档模式。

在NOARCHIVELOG模式的数据库中,除了数据字典的修改外,CREATE TABLE不会记录日志.

如果你想在NOARCHIVELOG模式的数据库上看到差别,可以把对表T的DROP TABLE和CREATE TABLE换成DROP INDEX和CREATE INDEX。

默认情况下,不论数据库以何种模式运行,这些操作都会生成日志。

因为不同的模式可能导致不同的行为。你的生产系统可能采用ARCHIVELOG模式运行.

倘若你执行的大量操作在ARCHIVELOG模式下会生成redo,而在NOARCHIVELOG模式下不会生成redo,

你肯定想在测试时就发现这一点,而不要等到系统交付给用户时才暴露出来!

查看是否归档

查看数据库是否开启归档

select name,log_mode from v$database;

启用归档

startup mount

alter database archivelog;

alter database open;

禁止归档

shutdown immediate

startup mount

alter database noarchivelog

alter database open

force logging(强制日志)模式:

如果数据库强制日志模式开启后,则Oracle无论什么操作都进行redo的写入。

查看强制日志模式

通过

select force_logging from v$database

可以看到当前数据库是否开启了强制日志模式状态

开启强制日志模式

如果未开启数据库强制日志模式(默认未开启),则可以通过

alter database force logging开启,之后Oracle无论什么操作都进行redo的写入,不依赖于数据库的归档模式等其他因素.

关闭强制日志模式

如果已经开启了数据库强制日志模式,则可以通过

alter database no force logging关闭强制日志模式。

使数据库恢复先前的设置,数据库是否写入redo由数据库的归档模式等其他因素决定

disable_logging

那么在Oracle内部还存在一个内部参数:_disable_logging 默认是false

通过更改为true可以让Oracle在修改表中的记录的时候完全不记录redo,这个参数要甚用,平时,我们只作为性能测试用。

查看:show parameter disa /disable/_disable_logging

开启:alter system set "_disable_logging"=true scope=both;

禁用:alter system set "_disable_logging"=false

表的归档模式

查看表的logging模式

查看表是否是logging状态用如下SQL:

select table_name,logging from dba_tables where table_name='tablename';

修改表的logging模式

修改表的logging状态sql:

alter table table_name nologging/logging

减少redo写入

本节所讲的都是当数据库未开启强制日志模式时的操作。

对象的操作在执行时会产生重做日志,采用某种方式,生成的redo会比平常(即不使用NOLOGGING子句时)少得多.

注意,这里说"redo"少得多,而不是"完全没有redo".所有操作都会生成一些redo,不论数据库的日志模式是什么,

所有数据字典操作都会计入日志。

如何减少redo

create table时减少redo的方法

创建表时crate table as加入nolongging选项减少redo,格式如下

create table [table_name] nologging as  [select表达式]。

insert into减少redo的方法

insert 大批量数据时加入/*+append */选项减少redo写入,格式如下

insert /*+append */ into   [table_name]  [select表达式]

数据库归档模式下生成redo规则

create table时nologging效果

归档模式下创建的表,默认为logging模式。

创建表时crate table as加入nolongging选项减少redo写入明显

验证

下面比较以下两种create table as时产生的redo size量。

SELECT a.NAME,

b.VALUE cur_size_byte,

round(b.VALUE / 1024, 3) || 'KB' cur_size_kb

FROM v$statname a, v$mystat b

WHERE a.statistic# = b.statistic#

AND lower(a.NAME) LIKE '%' || lower('redo size') || '%'

查询当前的重做日志大小记录下来

create table test_1 as select * from test;

SELECT a.NAME,

b.VALUE cur_size_byte,

round(b.VALUE / 1024, 3) || 'KB' cur_size_kb

FROM v$statname a, v$mystat b

WHERE a.statistic# = b.statistic#

AND lower(a.NAME) LIKE '%' || lower('redo size') || '%'

查询当前的重做日志大小减去前面记录下来的值计算刚才这个操作产生的redo大小标记为redo_1

SELECT a.NAME,

b.VALUE cur_size_byte,

round(b.VALUE / 1024, 3) || 'KB' cur_size_kb

FROM v$statname a, v$mystat b

WHERE a.statistic# = b.statistic#

AND lower(a.NAME) LIKE '%' || lower('redo size') || '%'

查询当前的重做日志大小记录下来

create table test_2 nologging as select * from test;

SELECT a.NAME,

b.VALUE cur_size_byte,

round(b.VALUE / 1024, 3) || 'KB' cur_size_kb

FROM v$statname a, v$mystat b

WHERE a.statistic# = b.statistic#

AND lower(a.NAME) LIKE '%' || lower('redo size') || '%'

查询当前的重做日志大小减去前面记录下来的值计算刚才这个操作产生的redo大小标记为redo_2

比较redo_1和redo_2的大小就知道crate table as加入nolongging或不加nologging选项的区别了

insert into时加入append效果

表模式logging

当表模式为logging状态时,无论是append模式还是no append模式,redo都会生成,即加入append选项无法生效。

验证

下面比较以下两种insert时产生的redo size量,可以看出redo量是差不多的。

计算重做大小的方法与上面的一样就不说了

1、insert /*+append */ into test_1 select * from test;

commit;

2、insert  into  test_1 select * from test;

commit;

表模式nologging

当表模式为nologging状态时,只有加入append模式会明显减少生成redo。

验证

1、insert /*+append */ into test_1 select * from test;

commit;

2、insert  into  test_1 select * from test;

commit;

数据库非归档模式生成redo规则

create table 使用nologging对产生redo的影响

非归档模式下创建的表,默认为nologging模式。

在NOARCHIVELOG模式的数据库中,除了数据字典的修改外,CREATE TABLE不会记录日志。

因此创建表时(crate table as)加入nologging选项减少redo写入不明显,即nologging选项加不加都差不多

验证

下面比较以下两种create table as时产生的redo size量。

create table test_1 as select * from test;

create table test_2 nologging as select * from test;

insert into时append效果

表模式logging

当表模式为logging状态时,加入append模式明显减少生成redo,而no append模式下不会减少生成。

验证

insert /*+append */ into test_1 select * from test;

commit;

insert  into  test_1 select * from test;

commit;

表模式nologging

当表模式为nologging状态时,append的模式会减少生成redo,而no append模式不会减少生成。

验证

insert /*+append */ into test_1 select * from test;

commit;

insert  into  test_1 select * from test;

commit;

其实就是直截加载与传统加载的区别

直接加载优势

直接加载比传统加载效率要高

不扫描原来的空数据块

不需要sql解析,减少系统的负载

不经过SGA

不走DBWR进程,走自己的专属进程,所以速度快

直接加载限制

不能加载簇表

锁定整个表,在表上有活动事务的时候不能加载

直接加载特点

直接加载是在所有数据块后面加载新数据块,修改高水位线,不扫描原来的空数据块。

直接加载只产生一点点的管理redo,因为要修改数据字典(也可以讲不产生redo)。

回滚,如果加载失败把新分配数据块抹掉就行了。

无需SGA,无需SQL解析,无需DBWR进程

实验

现在我们已经定义了test;

SQL> select count(*) from test;    现在表里没有记录数

  COUNT(*)

----------

         0

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='TEST'; 现在分配了1个区

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                     0      65536

[oracle@secdb1 ~]$ sqlldr userid=ls/ls control=leo_test.ctl data=leo_test.data log=leo_test.log    传统方式加载数据

LS@LEO> select count(*) from test;                   已经成功加载了100万条数据

  COUNT(*)

----------

   1000000

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='TEST'; 100万条数据占用28个区

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                      0      65536

TEST                                                                                      1      65536

TEST                                                                                      2      65536

TEST                                                                                      3      65536

TEST                                                                                      4      65536

TEST                                                                                      5      65536

TEST                                                                                      6      65536

TEST                                                                                      7      65536

TEST                                                                                      8      65536

TEST                                                                                      9      65536

TEST                                                                                     10      65536

TEST                                                                                     11      65536

TEST                                                                                     12      65536

TEST                                                                                     13      65536

TEST                                                                                     14      65536

TEST                                                                                     15      65536

TEST                                                                                     16    1048576

TEST                                                                                     17    1048576

TEST                                                                                     18    1048576

TEST                                                                                     19    1048576

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                     20    1048576

TEST                                                                                     21    1048576

TEST                                                                                     22    1048576

TEST                                                                                     23    1048576

TEST                                                                                     24    1048576

TEST                                                                                     25    1048576

TEST                                                                                     26    1048576

TEST                                                                                     27    1048576

28 rows selected

SQL> delete from test;                     删除100万条数据

1000000 rows deleted.

SQL> commit;                                           提交

Commit complete.

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='TEST';

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                      0      65536

TEST                                                                                      1      65536

TEST                                                                                      2      65536

TEST                                                                                      3      65536

TEST                                                                                      4      65536

TEST                                                                                      5      65536

TEST                                                                                      6      65536

TEST                                                                                      7      65536

TEST                                                                                      8      65536

TEST                                                                                      9      65536

TEST                                                                                     10      65536

TEST                                                                                     11      65536

TEST                                                                                     12      65536

TEST                                                                                     13      65536

TEST                                                                                     14      65536

TEST                                                                                     15      65536

TEST                                                                                     16    1048576

TEST                                                                                     17    1048576

TEST                                                                                     18    1048576

TEST                                                                                     19    1048576

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                     20    1048576

TEST                                                                                     21    1048576

TEST                                                                                     22    1048576

TEST                                                                                     23    1048576

TEST                                                                                     24    1048576

TEST                                                                                     25    1048576

TEST                                                                                     26    1048576

TEST                                                                                     27    1048576

28 rows selected

把数据都删除了还占用空间,oracle的delete操作不回收空间,只是把自己的记录标记为删除,实际呢还占用的空间不释放

[oracle@secdb1 ~]$ sqlldr userid=ls/ls control=leo_test.ctl data=leo_test.data log=leo_test.log    第二次传统方式加载数据

SQL> select count(*) from test;                   已经成功加载了100万条数据

  COUNT(*)

----------

   1000000

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='TEST';

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                      0      65536

TEST                                                                                      1      65536

TEST                                                                                      2      65536

TEST                                                                                      3      65536

TEST                                                                                      4      65536

TEST                                                                                      5      65536

TEST                                                                                      6      65536

TEST                                                                                      7      65536

TEST                                                                                      8      65536

TEST                                                                                      9      65536

TEST                                                                                     10      65536

TEST                                                                                     11      65536

TEST                                                                                     12      65536

TEST                                                                                     13      65536

TEST                                                                                     14      65536

TEST                                                                                     15      65536

TEST                                                                                     16    1048576

TEST                                                                                     17    1048576

TEST                                                                                     18    1048576

TEST                                                                                     19    1048576

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                     20    1048576

TEST                                                                                     21    1048576

TEST                                                                                     22    1048576

TEST                                                                                     23    1048576

TEST                                                                                     24    1048576

TEST                                                                                     25    1048576

TEST                                                                                     26    1048576

TEST                                                                                     27    1048576

28 rows selected

使用传统方式加载数据,会扫描原来的空数据块,会把新加载的数据插入到空数据块内,看我们还是使用原来的28个区

SQL> delete from test;                     这是第二次删除100万条数据

1000000 rows deleted.

SQL> commit;                                           提交

Commit complete.

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='TEST';

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                      0      65536

TEST                                                                                      1      65536

TEST                                                                                      2      65536

TEST                                                                                      3      65536

TEST                                                                                      4      65536

TEST                                                                                      5      65536

TEST                                                                                      6      65536

TEST                                                                                      7      65536

TEST                                                                                      8      65536

TEST                                                                                      9      65536

TEST                                                                                     10      65536

TEST                                                                                     11      65536

TEST                                                                                     12      65536

TEST                                                                                     13      65536

TEST                                                                                     14      65536

TEST                                                                                     15      65536

TEST                                                                                     16    1048576

TEST                                                                                     17    1048576

TEST                                                                                     18    1048576

TEST                                                                                     19    1048576

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                     20    1048576

TEST                                                                                     21    1048576

TEST                                                                                     22    1048576

TEST                                                                                     23    1048576

TEST                                                                                     24    1048576

TEST                                                                                     25    1048576

TEST                                                                                     26    1048576

TEST                                                                                     27    1048576

28 rows selected

delete还是不回收空间,我们依然占用着28个区

[oracle@secdb1 ~]$ sqlldr userid=ls/ls control=leo_test.ctl data=leo_test.data log=leo_test.log direct=true    直接方式加载数据

SQL> select segment_name,extent_id,bytes from user_extents where segment_name='TEST';

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                      0      65536

TEST                                                                                      1      65536

TEST                                                                                      2      65536

TEST                                                                                      3      65536

TEST                                                                                      4      65536

TEST                                                                                      5      65536

TEST                                                                                      6      65536

TEST                                                                                      7      65536

TEST                                                                                      8      65536

TEST                                                                                      9      65536

TEST                                                                                     10      65536

TEST                                                                                     11      65536

TEST                                                                                     12      65536

TEST                                                                                     13      65536

TEST                                                                                     14      65536

TEST                                                                                     15      65536

TEST                                                                                     16    1048576

TEST                                                                                     17    1048576

TEST                                                                                     18    1048576

TEST                                                                                     19    1048576

SEGMENT_NAME                                                                      EXTENT_ID      BYTES

-------------------------------------------------------------------------------- ---------- ----------

TEST                                                                                     20    1048576

TEST                                                                                     21    1048576

TEST                                                                                     22    1048576

TEST                                                                                     23    1048576

TEST                                                                                     24    1048576

TEST                                                                                     25    1048576

TEST                                                                                     26    1048576

TEST                                                                                     27    1048576

TEST                                                                                     28    1048576

TEST                                                                                     29    1048576

TEST                                                                                     30    1048576

TEST                                                                                     31    1048576

TEST                                                                                     32    1048576

TEST                                                                                     33    1048576

TEST                                                                                     34    1048576

TEST                                                                                     35    1048576

TEST                                                                                     36    1048576

TEST                                                                                     37    1048576

TEST                                                                                     38    1048576

TEST                                                                                     39    1048576

TEST                                                                                     40    1048576

TEST                                                                                     41    1048576

TEST                                                                                     42    1048576

TEST                                                                                     43    1048576

TEST                                                                                     44    1048576

TEST                                                                                     45    1048576

TEST                                                                                     46    1048576

TEST                                                                                     47    1048576

48 rows selected

发现同样的100万条记录,竟然占用了48个区,传统加载只用了28个,而我们使用直接加载到多了20个数据块,

对了直接加载不扫描原来的空数据块,会在所有数据块之后加载新的数据块插入数据修改高水位线HWM,

当提交事务之后,把高水位线移到新数据之后,其他的用户就可以看见了。

比较直接加载使用conventional 和direct方式产生的redo大小(可以通过/*+ append */模拟直接加载)。

明确:直接加载与logging配合下并不能显著的减少redo日志量

      直接加载与nologging配合下可以大幅度的减少redo日志量

SQL> create table leo_t1 as select * from test where 1=2;          创建leo_t1表

Table created.

SQL> alter table leo_t1 logging;                                               设置leo_t1表logging模式

Table altered.

SQL> set autotrace  traceonly;

SQL> insert into leo_t1 select * from leo_test_sqlload where rownum <= 20000;  采用传统方式加载2万条记录

20000 rows created.

Statistics   统计信息

----------------------------------------------------------

       1071  recursive calls

       2668  db block gets

       1860  consistent gets

        386  physical reads

    1680404  redo size                                                这是产生的日志量1680404

        680  bytes sent via SQL*Net to client

        603  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          6  sorts (memory)

          0  sorts (disk)

      20000  rows processed

SQL> rollback;                                                     回滚操作,使用undo表空间

Rollback complete.

SQL> insert /*+ append */ into leo_t1 select * from leo_test_sqlload where rownum <= 20000; 使用直接加载方式插入2万条记录

20000 rows created.

Statistics

----------------------------------------------------------

         94  recursive calls

        268  db block gets

       1294  consistent gets

        202  physical reads

    1627260  redo size                                当leo_t1为logging属性时,直接加载和传统加载产生redo日志差不多

        664  bytes sent via SQL*Net to client

        617  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          1  sorts (memory)

          0  sorts (disk)

      20000  rows processed

小结:这是因为在logging模式下,所有的数据块的改变都会产生redo日志,为以后恢复做准备,这时候直接加载没有多大的优势。

直接加载与nologging配合下可以大幅度的减少redo日志量

重大前提

如果你的数据库开启了force_logging=yes模式,那么不管你是传统加载还是直接加载都不会减少redo产生量

所以要想大幅度减少redo日志就必须满足3个条件

(1)关闭force_logging选项     alter database no force logging;   启动  alter database force logging;

(2)数据对象级别nologging模式 alter table leo_t1 nologging;

(3)直接加载                 insert /*+ append */ into 

数据库归档与redo日志量关系

数据库处于归档模式

  当表模式为logging状态时,无论是否使用append模式,都会生成redo.当表模式为nologging状态时,只有append模式,不会生成redo。

数据库处于非归档模式

  无论是在logging还是nologing的模式下,append的模式都不会生成redo,而no append模式下都会生成redo。

SQL> alter database no force logging;     

SQL> select force_logging from v$database;                       已经关闭force_logging选项

FOR

---

NO

SQL> alter table leo_t1 nologging;                                       设置leo_t1表nologging模式

Table altered.

SQL> select logging from user_tables where table_name='LEO_T1';

LOG

---

NO

SQL> select count(*) from leo_t1;                                       0条记录

  COUNT(*)

----------

         0

SQL> select index_name from user_indexes where table_name='LEO_T1';   表上没有索引

no rows selected

SQL> insert /*+ append */ into leo_t1 select * from leo_test_sqlload where rownum <= 20000;    直接加载

20000 rows created.

Statistics

----------------------------------------------------------

       1443  recursive calls

        649  db block gets

       1702  consistent gets

       1519  physical reads

      44900  redo size                                    直接加载产生的redo日志非常少

        658  bytes sent via SQL*Net to client

        617  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          9  sorts (memory)

          0  sorts (disk)

      20000  rows processed

SQL> rollback;

Rollback complete.

LS@LEO> insert into leo_t1 select * from leo_test_sqlload where rownum <= 20000;       传统加载

20000 rows created.

Statistics

----------------------------------------------------------

          4  recursive calls

       2207  db block gets

       1534  consistent gets

        441  physical reads

    1634064  redo size                                      传统加载产生的redo日志非常非常的多

        673  bytes sent via SQL*Net to client

        603  bytes received via SQL*Net from client

          4  SQL*Net roundtrips to/from client

          1  sorts (memory)

          0  sorts (disk)

      20000  rows processed

小结:直接加载与nologging配合下可以大幅度的减少redo日志量,因为插入的数据不产生redo日志,

所以在插入后要做备份操作,一旦数据损坏,就要使用备份来恢复,不能使用redo来恢复。注意要关闭force_logging选项

以上就是“Oracle数据库的事务日志怎么理解”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI