Usage of Oracle Block

本文详细介绍了Oracle数据库中插入、更新和删除操作对数据块的影响,涉及PCTFREE、PCTUSED参数以及高水标记(HWM)的概念。通过示例展示了数据在数据块中的存储变化,帮助理解Oracle的数据管理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       本文主要介绍插入(Insert),更新(Update),删除(Delete)操作时数据在数据块(Block)中的变化。首先简单讲一下几个相关的参数。

       一.相关参数

       在手动管理的表空间(Manually Managed Tablespace)中,用户可以使用PCTFREE和PCTUSED这两个存储管理参数来控制对某段(Segment)进行插入和更新操作时,如何利用属于此段的数据块(Data Block)中的可用空间。用户也可以在创建或修改索引时为其设定PCTFREE参数。

       1.PCTFREE

         PCTFREE参数用来设置一个数据块中至少需要保留多少可用空间(百分比),为数据块中已有的数据更新世可能发生的行数据长度增长做准备。例如,当用户用CREATE TABLE 语句创建表时指定了PCTFREE为10,那么此表对应的数据段中的每个数据块至少要保留10%的可用空间,以备块中已有数据更新时使用,只要数据块中数据区与数据块头的容量之和不超过1-PCTFREE的值,用户就可以向其中插入新数据。    

       2.PCTUSED

         PCTUSED参数用于决定一个数据块是否可以用户插入新数据,他的依据是数据区域和数据块头的容量之和占数据块全部容量的最大百分比,当一个数据块中的可用空间比例小于PCTFREE参数值时,Oracle认为此数据块无法被用户插入新数据,直到数据块中的数据区域和数据块头之和的比例小于PCTUSED参数值,Oracle才会再次使用这个块来插入新的数据。

       3.FreelistFreelist groups

         FreelistFreelist groups是可插入数据的数据块的列表与列表集。当有新数据插入时,Oracle通过查询此列表找到可以插入数据的数据块。block剩余空间不足以插入一条记录,同时该block的使用率已经超过PCTUSED定义的值并且该数据块位于freelist header处时,该块也会从freelist上摘走,术语(UNLINK)。当有数据删除(delete)的时候,只有该数据块(block)中的数据被删除到PCTUSED定义的值时,该数据块(block)才会重新被链接(LINK)freelist中。

       4.高水标记(high water mark)

         简单来说,HWM就是一个segment中已使用和未使用的数据块(block)的分界线,当请求新的空闲块,并且现有的空闲列表(freelist)中的块不能满足要求时,HWM指向的块将被标记为已使用,然后HWM将移动指向下一个未使用过的块。 

      Freelist只是管理高水位标志以下的空闲空间,而实际上一个segment可用的空闲空间包括两种类型:已经分配给这个segment但是从来没有使用过的高水位标志之上的blocks。位于高水位标志之下,被链接到freelist上的blocks。下图为数据块的使用示例:

block usage

      二.插入(Insert),更新(Update),删除(Delete)操作对数据块的影响

         创建一个名为test的表,并向里面插入三条记录用于测试。用dba用户登录创建PL/SQL过程show_space,用于显示某个表使用block的信息。show_space的使用参考文章:http://blog.youkuaiyun.com/huang_tg/archive/2010/07/09/5724499.aspx        

SQL> create table test

  2  (sno varchar2(10),

  3   sname varchar2(20));

表已创建。

SQL> insert into test values ('001','huang');

SQL> insert into test values ('002','ting');

SQL> insert into test values ('003','guang');

SQL> commit;

提交完成。

SQL> set serveroutput on

SQL> exec show_space('TEST');

Total Blocks............................3

Total Bytes.............................12288

Unused Blocks...........................1

Unused Bytes............................4096

Last Used Ext FileId....................1

Last Used Ext BlockId...................61573

Last Used Block.........................2

PL/SQL 过程已成功完成。

SQL> alter system dump datafile 1 block 61574;

系统已更改。

data_block_dump

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

tsiz: 0xfa0

hsiz: 0x18

pbl: 0x0296105c

bdba: 0x0040f086

flag=-------------

ntab=1

nrow=3

frre=-1

fsbo=0x18

fseo=0xf7a

avsp=0xf62

tosp=0xf62

0xe:pti[0]    nrow=3   offs=0    --本块存在3条记录

0x12:pri[0]   offs=0xf93    --记录的起始物理位置

0x14:pri[1]   offs=0xf87

0x16:pri[2]   offs=0xf7a

block_row_dump:

tab 0, row 0, @0xf93   --第一行数据开始的物理地址

tl: 13 fb: --H-FL-- lb: 0x1  cc: 2 --lb:表示属于XID 0x1 cc:表示有2字段

col  0: [ 3]  30 30 31 --字段1长度为3,数据30 30 31

col  1: [ 5]  68 75 61 6e 67 --字段2长度为5,数据68 75 51 6e 67

tab 0, row 1, @0xf87

tl: 12 fb: --H-FL-- lb: 0x1  cc: 2

col  0: [ 3]  30 30 32

col  1: [ 4]  74 69 6e 67

tab 0, row 2, @0xf7a

tl: 13 fb: --H-FL-- lb: 0x1  cc: 2

col  0: [ 3]  30 30 33

col  1: [ 5]  67 75 61 6e 67

end_of_block_dump

End dump data blocks tsn: 0 file#: 1 minblk 61574 maxblk 61574

         1.插入(Insert)数据对数据块的影响

           数据在oracle数据库中的存储是从block的底部开始的,遵循从下到上的规则。当一个新行被插入时,oracle首先搜索freelist (数据块中使用的空间未达到PCTUSED设置的值)中的空闲块,如果找到则插入数据。没有找到则使用HWM指向的数据块(block),同时移动HWM,使其指向下一个未使用过的数据块。如果行数据过大,一个数据块装不下,那么就会产生行链接。以下是向测试表中插入两条记录后数据块的变化:                  

SQL> insert into test values ('004','tang');

SQL> insert into test values ('005','yan');

SQL> commit;

提交完成。

data_block_dump

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

0xe:pti[0]    nrow=5   offs=0    --增加了2条记录

0x12:pri[0]   offs=0xf93

0x14:pri[1]   offs=0xf87

0x16:pri[2]   offs=0xf7a

0x18:pri[3]   offs=0xf6e    --新增加的004号记录

0x1a:pri[4]   offs=0xf63    --新增加的005号记录

block_row_dump:

tab 0, row 3, @0xf6e   --4条记录开始地址

tl: 12 fb: --H-FL-- lb: 0x2  cc: 2

col  0: [ 3]  30 30 34    --字段1长度为3,数据为30 30 34

col  1: [ 4]  74 61 6e 67 --字段1长度为4,数据为74 61 6e 67

tab 0, row 4, @0xf63   --5条记录开始地址

tl: 11 fb: --H-FL-- lb: 0x2  cc: 2

col  0: [ 3]  30 30 35     --字段1长度为3,数据为30 30 35

col  1: [ 3]  79 61 6e     --字段1长度为3,数据为79 61 6e

end_of_block_dump

End dump data blocks tsn: 0 file#: 1 minblk 61574 maxblk 61574

        2.删除(delete)数据对数据块的影响

          删除(delete):删除数据时,oracle并不回收被删除数据所占用的空间,只是做一个标记以表明,这部分空间可以重用。如果一个数据块因为删除了数据使得他的使用空间低于PCTUSED的值。那么这个数据块将被再次放到freelist中,当需要时就会被重用。一下是删除一条数据以后数据块中的变化:        

SQL> delete from test where sno='002' or sno='003';

SQL> commit;

提交完成。

SQL> select * from test;

SNO        SNAME

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

001        huang

004        tang

005        yan

SQL> exec show_space('TEST');

Total Blocks............................3

Total Bytes.............................12288

Unused Blocks...........................1

Unused Bytes............................4096

Last Used Ext FileId....................1

Last Used Ext BlockId...................61573

Last Used Block.........................2

PL/SQL 过程已成功完成。

SQL> alter system dump datafile 1 block 61574;

系统已更改。

block_row_dump:

tab 0, row 1, @0xf87         --002的记录位置,已经没有数据

tl: 2 fb: --HDFL-- lb: 0x1    

tab 0, row 2, @0xf7a         --003的记录位置,已经没有数据

tl: 2 fb: --HDFL-- lb: 0x1

end_of_block_dump

End dump data blocks tsn: 0 file#: 1 minblk 61574 maxblk 61574

SQL> insert into test values ('002','t');

SQL> insert into test values ('003','g');

SQL> commit;

提交完成。

SQL> alter system dump datafile 1 block 61574;

系统已更改。

block_row_dump:

tab 0, row 1, @0xf87     --被删除的002号记录

tl: 2 fb: --HDFL-- lb: 0x1

tab 0, row 2, @0xf7a     --被删除的003号记录

tl: 2 fb: --HDFL-- lb: 0x1

tab 0, row 5, @0xf5a      --新增加的002号记录

tl: 9 fb: --H-FL-- lb: 0x2  cc: 2

col  0: [ 3]  30 30 32     --新插入的002号记录的数据

col  1: [ 1]  74

tab 0, row 6, @0xf51      --新增加的003号记录

tl: 9 fb: --H-FL-- lb: 0x2  cc: 2

col  0: [ 3]  30 30 33    --新插入的003号记录的数据

col  1: [ 1]  67

end_of_block_dump

End dump data blocks tsn: 0 file#: 1 minblk 61574 maxblk 61574

        3.更新(update)数据对数据块的影响    

          更新(update):数据被更新时,oracle首先使用数据所在数据块(block)所预留的空闲空间(PCTFREE)来存储数据更新可能带来的行数据增大。如果更新产生的新数据过大,造成数据块(block)无法装下新的数据,那么将被拷贝到一个有足够空间的数据块中,而原始块则会存储一个指向更新够新数据的开始地址。以下是更新两条记录以后数据块的变化:

 

SQL> update test set sname='ting' where sno='002';

SQL> update test set sname='guang' where sno='003';

SQL> commit;

提交完成。

SQL> alter system dump datafile 1 block 61574;

系统已更改。

block_row_dump:

tab 0, row 5, @0xed6           --5行记录(新插入的002号记录)

tl: 12 fb: --H-FL-- lb: 0x1  cc: 2

col  0: [ 3]  30 30 32

col  1: [ 4]  74 69 6e 67      --数据已经被更新

tab 0, row 6, @0xec9           --6行记录新插入的003号记录

tl: 13 fb: --H-FL-- lb: 0x1  cc: 2

col  0: [ 3]  30 30 33

col  1: [ 5]  67 75 61 6e 67    --数据已经被更新

end_of_block_dump

End dump data blocks tsn: 0 file#: 1 minblk 61574 maxblk 61574

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值