由读一致性分析undo

下面通过undo的一致性读分析undo:

[[email protected] ~]$ lsb_release -a

LSB Version:    :core-3.1-ia32:core-3.1-noarch:graphics-3.1-ia32:graphics-3.1-noarch

Distributor ID: EnterpriseEnterpriseServer

Description:    Enterprise Linux Enterprise Linux Server release 5.5 (Carthage)

Release:        5.5

Codename:       Carthage

SQL> select * from v$version where rownum<2;

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

SQL> create table t(id number,name varchar2(10));

表已创建。

已用时间:  00: 00: 00.15

SQL> set timing off;

SQL> show user;

USER 为 "HR"

SQL> insert into  t values(1,‘a‘);

已创建 1 行。

SQL> insert into t values(2,‘b‘);

已创建 1 行。

SQL> commit;

提交完成。

SQL> update t set name=‘c‘ where id=1;

已更新 1 行。

SQL> select * from t;

ID NAME

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

1 c

2 b

注意没提交。

重新打开一个session:

SQL> select * from t;

ID NAME

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

1 a

2 b

此时还是读取到修改之前的数据,这里的a是重undo里读取的,下面dump分析这个过程:

SQL> select t.*,rowid from t;

ID NAME       ROWID

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

1 c          AAASunAAEAAABuuAAA

2 b          AAASunAAEAAABuuAAB

我们利用oracle提供的包,可以获得第一条数据所在的数据文件号及块号:

SQL> show user;

USER 为 "SYS"

SQL> select dbms_rowid.rowid_relative_fno(rowid) fno,dbms_rowid.rowid_block_number(rowid) bno from hr.t;

FNO        BNO

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

4       7086

4       7086

此时我们可以dump 4号文件的第7086块:

SQL> alter system dump datafile 4 block 7086;

系统已更改。

下面是摘自部分转储文件:

*** 2015-04-20 15:26:34.151

Block header dump:  0x01001bae

Object id on Block? Y

seg/obj: 0x12ba7  csc: 0x00.6658e2  itc: 2  flg: E  typ: 1 - DATA

brn: 0  bdba: 0x1001ba8 ver: 0x01 opc: 0

inc: 0  exflg: 0

Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0003.017.0000098a  0x00c009ac.02f0.24  C---    0  scn 0x0000.0066582c

0x02   0x0008.00d.00000a84  0x00c02e17.0258.28  ----(表示事务锁定)    1(锁定一条数据)  fsc
0x0000.00000000    =>0x2列已经被锁定了

bdba: 0x01001bae                                                                                                                                               uba:undo block address

data_block_dump,data header at 0xa18264

===============

tsiz: 0x1f98

hsiz: 0x16

pbl: 0x00a18264

76543210

flag=--------

ntab=1

nrow=2

frre=-1

fsbo=0x16

fseo=0x1f88

avsp=0x1f70

tosp=0x1f70

0xe:pti[0] nrow=2 offs=0

0x12:pri[0] offs=0x1f90

0x14:pri[1] offs=0x1f88

block_row_dump:

tab 0, row 0, @0x1f90

tl: 8 fb: --H-FL-- lb(锁标记): 0x2  cc:
2       第一行第二列已经被上锁了,被一个事务锁定。 lb:lock
byte

col  0: [ 2]  c1 02                       =>这列是从4号文件7086块中读取的

col  1: [ 1]  63                            63代表是c,实际已经被改了

tab 0, row 1, @0x1f88

tl: 8 fb: --H-FL-- lb: 0x0  cc: 2

col  0: [ 2]  c1 03

col  1: [ 1]  62

end_of_block_dump

End dump data blocks tsn: 4 file#: 4 minblk 7086 maxblk 7086

第二个session我们查出的第一行第二列却是a,也是从4号文件7086个块上读取得,但是发现第二列已经被上锁,不能读取。

我们通过uba提供的地址,可以获取修改之前的数据a存放的位置:

uba:

0x00c02e17.0258.28

先把这个十六进制数转换成十进制数,oracle提供的十进制包可以获取文件号及块号:

SQL> select to_number(‘00c02e17‘,‘XXXXXXXXXXXXXXXXXX‘) from dual;

TO_NUMBER(‘00C02E17‘,‘XXXXXXXXXXXXXXXXXX‘)

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

12594711

SQL> select dbms_utility.data_block_address_file(12594711) from dual;

DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(12594711)

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

3

SQL> select dbms_utility.data_block_address_block(12594711) from dual;

DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(12594711)

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

11799

在第二个session中,oracle提示读取第一行第二列需要到3号文件上第11799号块上读取:

SQL> alter system dump datafile 3 block 11799;

系统已更改。

下面宅在部分转储文件:

uba: 0x00c02e17.0258.25 ctl max scn: 0x0000.00665307 prv tx scn: 0x0000.00665325

txn start scn: scn: 0x0000.006658a2 logon user: 91

prev brb: 12594708 prev bcl: 0

KDO undo record:

KTB Redo

op: 0x03  ver: 0x01

compat bit: 4 (post-11) padding: 1

op: Z

Array Update of 1 rows:

tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 191

ncol: 2 nnew: 1 size: 0

KDO Op code:  21 row dependencies Disabled

xtype: XAxtype KDO_KDOM2 flags: 0x00000080  bdba: 0x01001bae  hdba: 0x01001baa

itli: 2  ispac: 0  maxfr: 4858

vect = 3

col  1: [ 1]  61

End dump data blocks tsn: 2 file#: 3 minblk 11799 maxblk 11799

所以通过undo读取了61(代表a)

我们查看数据文件3是什么文件类型:

select * from dba_data_files where file_id=3;

是undo数据文件。

SQL> show parameter undo;

NAME                                 TYPE        VALUE

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

undo_management                      string      AUTO

undo_retention                       integer     900

undo_tablespace                      string      UNDOTBS1

默认的是undotbs1表空间,可以创建很多undo表空间,但是一个实例只用一个undo表空间。

undo表空间是有undo segments 组成,查看有多少undo段:

select * from dba_rollback_segs;

注意上面的owner列,如果是public,则该实例创建的undo段可以被数据库其他实例使用,但是sys表示的是私有undo段,只可以被该undo段创建者使用。

注意到undo段的状态了没,现在默认的undo表空间是undotbs1,所以该undo段都是在线,undo_w表空间的undo段都是离线。

我们可以通过修改参数undo_tablespace设置默认undo表空间。

oracle对于处于online的undo段进行监视,通过视图v$rollstat查看:

上面总共有11条,usn是undo段编号

一个事务使用一个undo段

下面执行一个事物:

SQL> update t set name=‘c‘ where id=1;

已更新 1 行。

select * from v$transaction;

注意XIDUSN列表示的是undo段编号,此时该事务使用的是10号undo段

查看10号undo段:

select * from v$rollstat;

XACTS列表示的是该10号undo段上具有活动的事务数量

此时修改默认undo表空间:

SQL> alter system set undo_tablespace=undo_w;

系统已更改。

SQL>  show parameter undo;

NAME                                 TYPE        VALUE

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

undo_management                      string      AUTO

undo_retention                       integer     900

undo_tablespace                      string      UNDO_W

此时查看undo段状态:

select  * from dba_rollback_segs;

undotbs1里的undo段除了10号,其他的都处于offline,因为它任被使用,事务结束后,自动变为offline

通过查看视图:

select * from v$rollstat;

发现10号undo段状态是pending  offline(pending在等待…期间)

会疑问,每个回滚段段上到底可以被几个事务使用呢?

SQL> show parameter roll

NAME                                 TYPE        VALUE

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

fast_start_parallel_rollback         string      LOW

rollback_segments                    string

transactions_per_rollback_segment    integer     5

可以被5个事务使用,但是这是在undo表空间没有自动管理之前,自从undo表空间自动管理后,该parameter不起作用。

一个undo段只能被一个事务使用,若undo被事务用完后,则oracle background  process  smon  自动创建undo段.

如果一个回滚段被多个事务使用的话,undo段头会有等待,影响并发性,我们可以通过视图V$WAITSTAT查看等待事件:

select * from v$waitstat;

可以通过执行多个事务,模拟smon自动创建undo段,自行模拟试验。(smon创建的undo段不会因为事务结束而回收)

下面看一下一个很重要的参数:undo_retention单位是秒(表示的是事务提交以后,放在undo里的数据保留的时间)

SQL>  show parameter undo;

NAME                                 TYPE        VALUE

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

undo_management                      string      AUTO

undo_retention                       integer     900

undo_tablespace                      string      UNDO_W

SQL> show parameter roll

很有名的oracle一个错误:ORA-01555(快照太旧)

实际情况下查询发生在修改之前,比较少。

出现这个错的可能情况:

undo表空间太小

查询数据的时间过长(sql查询性能差)

undo_rentention太小

我们通过视图dba_tablespaces,引出一个参数:

SELECT TABLESPACE_NAME,RETENTION FROM DBA_TABLESPACES;

retention这列,undo表空间缺省的是NOGUARANTEE,但是我们可以修改这个参数,强制保留。

SQL> alter tablespace undotbs1 retention GUARANTEE;

表空间已更改。

一定会保留900秒。

当让可以改undo_rentention

SQL> alter system set undo_retention=1200;

系统已更改。

上面列出的出现ORA-01555的三种情况,这三者之间有关系,比如增加了undo_rentention,从而需要的undo表空间要更多。

oracle里提供了undo  advisor(顾问),我们可以根据这个,来平衡这几者关系,进入到OEM:

[[email protected] ~]$ emctl start dbconsole

Oracle Enterprise Manager 11g Database Control Release 11.2.0.1.0

Copyright (c) 1996, 2009 Oracle Corporation.  All rights reserved.

https://diy_os:1158/em/console/aboutApplication

Starting Oracle Enterprise Manager 11g Database Control .......

进入em后,在自动管理界面,提供了这一张图:

根据undo_rentention的大小,来确定所需的undo表空间的大小,可以更改分析时段,会提供建议图形界面。

图形是如何作出的呢?

有一个公式:

UndoSpace = [UR * (UPS * DBS)] + (DBS*24)

UR:undo_rentention in seconds

UPS:number of undo data blocks generated per second

DBS:overhead varies based on extent and file size(db_block_size)实际就是块大小:show parameter  db_block;

我们可以根据oracle的一个视图:v$undostat;

每十分钟计算undo的数量。可以根据这个视图可以画出上述图形。

时间: 2024-08-03 23:15:07

由读一致性分析undo的相关文章

数据库的读一致性分析

前言 提起数据库的事务,我们就会想到ACID特性: A:Atomicity 原子性    事务中包含的各种操作,要么一起成功,要么全部失败 C:Consistency 一致性  事务从一个一致性的状态转变成另一个一致性的状态 I:Isolation 隔离性   各个事务之间的可见程度 D:Durability 持久性  数据库中的数据的改变应该是可以持久存储的 本篇博客将以MySQL为例分析数据库的读一致性.想分析清楚一致性,必先了解隔离级别. 数据库的隔离级别 在SQL标准中是定义了几种隔离级

事务的特性、事务并发、事务读一致性问题

1 什么是数据库的事务? 1.1 事务的典型场景 在项目里面,什么地方会开启事务,或者配置了事务?无论是在方法上加注解,还 是配置切面 <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" rollback-for="Throwable"

oracle如何保证读一致性

oracle保证读一致性原理 1:undo segment的概念 当数据库进行修改的时候,需要把保存到以前的old的数据保存到一个地方,然后进行修改,用于保存old数据的segment 就是undo segment. 以前老的东西是可以被覆盖掉的,因为undo segment是一种循环利用的方式. 看下图 如上图所示: 当oracle开启一个事务对table表中的数据进行修改,修改的那个数据(行数据)会被拷贝到 右图 undo  segment(用圆形表示是因为表示会被覆盖)中,这个时候事务没有

探讨SELECT语句的元数据&amp;amp;动态取样&amp;amp;读一致性导致的一致性读和递归操作

前几天,论坛上的同行在讨论SELECT语句的元数据,动态取样和读一致性导致的一致性读和递归问题,今天有时间,就试着进行了测试,本人测试环境如下: win7_64+Oracle11.2.0.4_64 那么,下面就说下测试过程: 1.元数据:当用户向数据库发出SELECT语句后,在解析和执行过程中,肯定是需要读取SELECT相关的元数据,这样,SELECT的统计数据中就会包含递归操作,做这个测试的前提是要把其他因素排除掉(动态取样,一致性读): session1: session2: 由上可见,在表

数据库中的读一致性和脚本匹配

如果你想在函数中运行查询,而这个函数又要在SQL中调用,这时我们需要小心读一致性的问题了.如果这些函数要在一个运行时间很长的查询或者事务中调用,我们可能需要使用下面的命令在当前事务的SQL语句间强制保持读一致性  SET TRANSACTION READ ONLY sql数据库中的匹配1. "_"匹配任何单个字符2. "%"匹配任意数目字符(包括零个字符)3.  "*"匹配0个或多个在它前面的字符4. "[]"匹配在方括号中的

关系型数据库的隔离级别 读一致性

来自网络: 三种可防止的现象: 脏读(dirty read):事务可以读取其他事务还没有提交的修改: 不可重复读(nonrepeatable read):事务读取先前曾读取过的数据,发现其他的已提交事务修改或删除了要读取的数据: 幻象读(phantom read):事务再次执行一个查询,发现其他已提交事务插入了新的满足当前查询条件的数据. 针对以上三种现象,SQL92标准指定了4种隔离制度,这4种隔离制度一种比一种严格. Read uncommitted:允许脏读.不可重复读和幻象读: Read

块设备的读流程分析

关于VFS的通用读,我们不做考虑,本文以如下函数为根,往下分析: do_generic_mapping_read(*ppos,*mapping,*desc) 本函数的目的是,从磁盘读数据到用户态, 先是从*ppos开始的页,一直读到*ppos+desc->count 为止的,这么多个页, 然后拷贝desc->count字节的数据到用户态. 也即,从磁盘读到内存缓冲区是按页读的,而从内存缓冲区读到用户态是按字节的. 函数核心是调用 mapping->a_ops->readpage(f

深入解读阿里云数据库POLARDB核心功能会话读一致性

POLARDB架构 我们知道,POLARDB是一个由多个节点构成的数据库集群,一个主节点,多个读节点.对外默认提供两个地址,一个是集群地址,一个是主地址,推荐使用集群地址,因为它具备读写分离功能可以把所有节点的资源整合到一起对外提供服务. MySQL读写分离解决和引入的问题 用过MySQL的都知道,MySQL的主从复制简单易用,非常流行,通过把主库的Binlog异步地传输到备库并实时应用,一方面可以实现高可用,另一方面备库也可以提供查询,来减轻对主库的压力. 虽然备库可以提供查询,但存在两个问题

ORACLE 物理读 逻辑读 一致性读 当前模式读总结浅析

在ORACLE数据库中有物理读(Physical Reads).逻辑读(Logical Reads).一致性读(Consistant Get).当前模式读(DB Block Gets)等诸多概念,如果不理解或混淆这些概念的话,对你深入理解一些知识无疑是一个障碍,但是这些概念确实挺让让人犯晕的.下面我们总结.学习一下这方面的知识点.捋一捋他们的关系和特点,希望对你有所帮助. 物理读(Physical Reads) 从磁盘读取数据块到内存的操作叫物理读,当SGA里的高速缓存(Cache Buffer