【开发篇sql】 基础概述(二) undo和redo

2undoredo

Undo

 

Oracle将所有的数据更改记录在undo,这些记录信息可以使oracle使用rollback来撤销更改操作。Undo的机制主要有两个目的:一是用来允许读不能阻塞写入,写入不能阻塞读,二是可以使事务能够rollback(回滚)。

事务能够产生undo(回滚),且产生的undo记录数量可以在动态性能视图V$transaction中得到。用一个例子来看看undo的产生:

SQL> set autocommit off;

SQL> insert into t_test_undo values (2,'asd');

 

1 row created.

 

SQL>

SQL> select used_urec from v$session s,v$transaction t where

  2  s.audsid = sys_context('userenv','sessionid') and

  3  s.taddr = t.addr;

 

 USED_UREC

----------

         1

上面的操作产生了1undo记录,再看看一次插入多条记录的情况:

SQL> insert into t_test_undo

  2  select rownum + 50000, object_name from all_objects where rownum < 51;

 

 

50 rows created.

 

SQL> SQL> select used_urec from v$session s, v$transaction t

  2   where s.audsid=sys_context('userenv', 'sessionid') and

  3         s.taddr = t.addr;

 

 USED_UREC

----------

         2

上面的语句也只产生了一条undo

然后看看update的情形:

SQL> update t_test_undo a set a.b = 'asdsd' where a.a = 1;

 

1 row updated.

 

SQL> select used_urec from v$session s, v$transaction t

  2   where s.audsid=sys_context('userenv', 'sessionid') and

  3         s.taddr = t.addr;

 

 USED_UREC

----------

         3

这个update语句也产生了1undo记录,再看看delete的情形:

SQL> delete from t_test_undo a where a.a <10;

 

2 rows deleted.

 

SQL> select used_urec from v$session s, v$transaction t

  2   where s.audsid=sys_context('userenv', 'sessionid') and

  3         s.taddr = t.addr;

 

 USED_UREC

----------

         5

可以看出,delete的每一条记录都产生了一个undo记录。

由此可以大概对比一下不同的语句产生的undo大小。

SQL>

SQL>

SQL> insert into t_test_undo values (10, 'asd');

 

1 row created.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

    XIDUSN     UBAREC     UBABLK  USED_UBLK  USED_UREC

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

         9         17        336          1          1

 

SQL> commit;

 

Commit complete.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

no rows selected

 

SQL> update t_test_undo a set a.b = 'qwe' where a.a = 10;

 

1 row updated.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

    XIDUSN     UBAREC     UBABLK  USED_UBLK  USED_UREC

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

         7          6       2701          1          1

 

SQL> commit;

 

Commit complete.

 

SQL> delete from t_test_undo a where a.a = 10;

 

1 row deleted.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

    XIDUSN     UBAREC     UBABLK  USED_UBLK  USED_UREC

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

         3         25       1057          1          1

 

SQL> commit;

 

Commit complete.

 

SQL> insert into t_test_undo values (10, 'asd');

 

1 row created.

 

SQL> update t_test_undo a set a.b = 'qwe' where a.a = 10;

 

1 row updated.

 

SQL> delete from t_test_undo a where a.a = 10;

 

1 row deleted.

 

SQL> select a.XIDUSN, a.UBAREC, a.UBABLK, a.USED_UBLK, a.USED_UREC

  2    from v$transaction a;

 

    XIDUSN     UBAREC     UBABLK  USED_UBLK  USED_UREC

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

         2         38      10021          1          3

 

SQL>

 

一般来说,insert产生了最少的undo,因为insert行的反操作是delete行,只记录插入记录的rowiddelete因为需要把整行的前映像记录到undo,所以产生最多的undoupdate需要记录行中被更新的字段部分的前映像,因此一般来说介于insertdelete之间。

 

回滚段可以说是用来保持数据变化前映像而提供一致性读和保证事务完整性的一段存储区域。当一个事务开始的时候,首先把变化前的数据和变化后的数据先写入日志缓冲区,然后吧变化前的数据写入回滚段,最后才在数据缓冲区中修改。

 

Undo segment头部包含记录了当前事务使用的undo segment信息的一张表。一系列事务只使用一个undo segment存储所有数据。许多并发的事务可以使用同一个undo segment

 

再来看看与undo相关的ora-01555

SQL> host oerr ora 1555

01555, 00000, "snapshot too old: rollback segment number %s with name \"%s\" too small"

// *Cause: rollback records needed by a reader for consistent read are

//         overwritten by other writers

// *Action: If in Automatic Undo Management mode, increase undo_retention

//          setting. Otherwise, use larger rollback segments

 

在相对稳定的数据库中,出现这个错误大多数时候是代码需要调整,或者由于业务需要在某一时段进行大批量的业务处理,而对一些较大的查询产生了影响。涉及到的undo的优化或者sql的优化在性能调整一章中详述。

 

 

Oraclesegment信息可以在dba_segments或者sys_dba_segs中查看,从下面的输出信息中可以看到几个比较重要的段对象,如tableindexrollback

SQL> select distinct segment_type from sys_dba_segs;

 

SEGMENT_TYPE

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

LOBINDEX

INDEX PARTITION

TABLE PARTITION

NESTED TABLE

ROLLBACK

LOB PARTITION

LOBSEGMENT

INDEX

TABLE

CLUSTER

TYPE2 UNDO

 

11 rows selected.

 

Redo

 

undo不同,undo是产生使操作撤销的信息,而redo是产生使操作重做的信息。Oracleredo有两种:online redo log(联机),archivelog(归档)

Lgwr循环的写入联机日志,当前日志日满后,lgwr写下一个日志。Lgwr总是在一下条件之一满足之时将缓冲重做日志写入磁盘:

1,每三秒;2,每当满1/31MB3碰到任何事务commit

在事务commit或者rollback之前往往已经完成了一下工作:

已经在sga中产生了回滚段记录,用于撤销

已经在sga中产生了修改数据块

已经在sga中产生了回滚和修改的重做,是的以上2个操作可以重做

根据lgwr的刷新特点,一部分数据可能已经刷新到了磁盘

已经获得了所有的锁定

commit时,要做的工作如下:

        为事务产生scnlgwr写磁盘,释放锁定,访问修改事务块,并清除之。

rollback时,要做的工作如下:

        使用回滚段的数据来撤销修改,释放锁定。

同样的,dmlredo产生的影响也是能够测定的。

下列语句依次执行:

select a.SID, a.VALUE

  from v$mystat a, v$statname b

 where a.STATISTIC# = b.STATISTIC#

   and b.NAME like 'redo_size';

insert into t_test_undo values (12, '123');

commit;

select a.SID, a.VALUE

  from v$mystat a, v$statname b

 where a.STATISTIC# = b.STATISTIC#

   and b.NAME like 'redo_size';

update t_test_undo a set a.b = '321' where a = 12;

commit;

select a.SID, a.VALUE

  from v$mystat a, v$statname b

 where a.STATISTIC# = b.STATISTIC#

   and b.NAME like 'redo_size';

delete t_test_undo where a.a = 12;

commit;

select a.SID, a.VALUE

  from v$mystat a, v$statname b

 where a.STATISTIC# = b.STATISTIC#

   and b.NAME like 'redo_size';

 

得到的redo size数值如下表:

操作

Sid

Redo size

初始

144

0

Insert 一行

144

548

Update 一行

144

1140

Delete 一行

144

1732

 

同样可以测试一次插入多行,更新多行和删除多行对redo的产生量,并且可以测试逐条提交和一次提交对redo的产生量。如果不结合起来看undoredo的影响而来调整应用,很多时候结果往往是不确定的。值得注意的是触发器的不同类型对redo的产生也有影响,比如对update使用after触发器,将不会影响重做。开发过程中,可以大致了解一下重做的数量:估计事务的大小,需要修改的数据量,提交的频率,dml类型占比(考虑到update产生大约2倍的重做,insertdelete大约为1倍)。而以上的表中似乎看不到不同dmlredo的区别,这是因为b的字段类型为varchar2(20),本身的修改量很小,如果吧字段修改为char(2000),则数字规律很明显,有关字符类型的细节在数据库设计一章节中详述。

 

另外redo是备份和恢复的一个支撑原理。有关联机日志和归档日志的管理和使用在备份恢复一章中详解。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/16179598/viewspace-662794/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/16179598/viewspace-662794/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值