oracle非分区字段如何update,非分区键的GLOBAL分区索引键值更新会造成麻烦吗?

我们都知道如果想修改分区表的分区键的值如果跨越了分区,那么必须加入ENABLE ROW MOVEMENT 进行,因为此时可能的ROWID会出现变动,

关于ROWID 如下:

Object ID (4 bytes) + DBA (4 bytes) + Row (2 bytes)

其中DBA包含了BLOCK地址和DATAFILE地址,如果UPDATE分区键的记录,可能的DATAFILE和BLOCK 都需要变动,所以要开启ENABLE ROW MOVEMENT。

而修改分区索引的键值在多个分区中移动为什么没有问题呢?如下:

SQL> CREATE INDEX month_ix ON testpar1(ic)

2     GLOBAL PARTITION BY RANGE(ic)

3        (PARTITION pm1_ix VALUES LESS THAN (1000),

4         PARTITION pm2_ix VALUES LESS THAN (2000),

5         PARTITION pm3_ix VALUES LESS THAN (3000),

6         PARTITION pm4_ix VALUES LESS THAN (4000),

7         PARTITION pm5_ix VALUES LESS THAN (5000),

8         PARTITION pm6_ix VALUES LESS THAN (6000),

9         PARTITION pm7_ix VALUES LESS THAN (7000),

10         PARTITION pm8_ix VALUES LESS THAN (8000),

11         PARTITION pm12_ix VALUES LESS THAN (MAXVALUE));

建立一个范围分区索引,然后我们进行UPDATE跨分区的,注意这里使用GLOBAL分区,这样我们我们用于测试修改非表分区字段,而是分区索引字段的值进行变动分区

SQL> update testpar1 set ic=10040 where ic=999;

1 row updated

此行必然造成分区间的移动数据,但是是没有问题的,如下我们通过DUMP进行仔细的分析一次

进行索引块截取一部分

row#0[8020] flag: ------, lock: 0, len=12

col 0; len 2; (2):  c1 02

col 1; len 6; (6):  02 00 0d f3 00 00

row#1[8008] flag: ------, lock: 0, len=12

col 0; len 2; (2):  c1 03

col 1; len 6; (6):  02 00 0d f3 00 01

row#2[7996] flag: ------, lock: 0, len=12

col 0; len 2; (2):  c1 04

col 1; len 6; (6):  02 00 0d f3 00 02

可以看到COL 1就是ROWID,这里的ROWID使用的是SHORT模式如下:

DBA (4 bytes) + Row (2 bytes)

这里我们取值

col 0; len 2; (2):  c1 03

col 1; len 6; (6):  02 00 0d f3 00 01

进行COL0换算

SQL> select to_number('c1','xxxxxx') from dual;

TO_NUMBER('C1','XXXXXX')

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

193

SQL> select to_number('03','xxxxxx') from dual;

TO_NUMBER('03','XXXXXX')

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

3

指数 193-193=0

数字1 (3-1)*100^0=2

所以这里COL0的数据位实际是2

而ROWID是02 00 0d f3 00 01,进行换算

SQL> select to_number('02000df3','xxxxxxxxx') from dual;

TO_NUMBER('02000DF3','XXXXXXXX

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

33558003

SQL> SELECT dbms_utility.data_block_address_block(33558003) "BLOCK",

2          dbms_utility.data_block_address_file(33558003) "FILE"

3       FROM dual;

BLOCK       FILE

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

3571          8

而0001就是第二行而已,实际这行的ROWID对应了FILE 8 BLOCK 3571的第二行

然后我们取出表中原始记录的ROWID

SQL> select dump(rowid,16) from testpar1 where ic=2;

DUMP(ROWID,16)

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

Typ=69 Len=10: 0,1,c0,80,2,0,d,f3,0,1

这个结果和INDEX中的ROWID

col 1; len 6; (6):  02 00 0d f3 00 01

完全一致,然后我们进行对原表记录进行更改进行跨索引跨分区测试

SQL> update testpar1 set ic=30000 where ic=2;

1 row updated

SQL> commit;

Commit complete

这样实际上我们索引记录已经由分区pm1_ix移动到MAXVALUE分区pm12_ix,这种情况下我们再来看源行的ROWID

SQL> select dump(rowid,16) from testpar1 where ic=30000;

DUMP(ROWID,16)

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

Typ=69 Len=10: 0,1,c0,80,2,0,d,f3,0,1

可以看到ROWID并没有改变,这是一定的。

然后我们在索引中找到这个块,但是如何中得到呢?由于索引是排序好的结构30000是其中最大的数据,找到这个30000的值我们需要找到最后一个有数据的索引块

首先DUMP这个pm12_ix的 BMB LEVEL 3块也就是段头块关注如下数据:

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

Segment Type: 2 nl2: 1      blksz: 8192   fbsz: 0

L2 Array start offset:  0x00001434

First Level 3 BMB:  0x00000000

L2 Hint for inserts:  0x02404cc9

Last Level 1 BMB:  0x02404cc8

Last Level II BMB:  0x02404cc9

Last Level III BMB:  0x00000000

Map Header:: next  0x00000000  #extents: 2    obj#: 114826 flag: 0x10000000

Inc # 0

Extent Map

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

0x02404cc8  length: 8

0x02404cd0  length: 8

Auxillary Map

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

Extent 0     :  L1 dba:  0x02404cc8 Data dba:  0x02404ccb

Extent 1     :  L1 dba:  0x02404cc8 Data dba:  0x02404cd0

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

可以清楚的看到EXTENT 0和1实际由一个L1块进行管理0x02404cc8,然后我们DUMP出这个L1块

关注如下信息:

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

DBA Ranges :

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

0x02404cc8  Length: 8      Offset: 0

0x02404cd0  Length: 8      Offset: 8

0:Metadata   1:Metadata   2:Metadata   3:25-50% free

4:FULL   5:FULL   6:FULL   7:FULL

8:FULL   9:unformatted   10:unformatted   11:unformatted

12:unformatted   13:unformatted   14:unformatted   15:unformatted

可以看到这里实际到了第九个块8:FULL,注意这里0:Metadata   1:Metadata   2:Metadata 实际上是

BMB 1,BMB 2,段头和BMB 3原数据块。

这样实际我们进行0x02404cd0的DUMP就可以找到数据了。

SQL> select to_number('02404cd0','xxxxxxxxx') from dual;

TO_NUMBER('02404CD0','XXXXXXXX

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

37768400

SQL>

BLOCK       FILE

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

19664          9

进行dump发现数据就在最后如下:

row#84[6928] flag: ------, lock: 0, len=12

col 0; len 2; (2):  c3 02

col 1; len 6; (6):  02 40 4c 83 01 e1

row#85[6914] flag: ------, lock: 0, len=14

col 0; len 4; (4):  c3 02 01 29

col 1; len 6; (6):  02 00 0d f5 01 a8

row#86[6902] flag: ------, lock: 2, len=12

col 0; len 2; (2):  c3 04

col 1; len 6; (6):  02 00 0d f3 00 01

----- end of leaf block dump -----

End dump data blocks tsn: 4 file#: 9 minblk 19664 maxblk 19664

这里我们找到了

row#86[6902] flag: ------, lock: 2, len=12

col 0; len 2; (2):  c3 04

col 1; len 6; (6):  02 00 0d f3 00 01

进行换算COL 0

指数 195-193=2

数字1 (4-1)*100^2=30000

可以看出没有问题就是我们修改的哪一行在关注ROWID

col 1; len 6; (6):  02 00 0d f3 00 01

SQL> select dump(rowid,16) from testpar1 where ic=30000;

DUMP(ROWID,16)

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

Typ=69 Len=10: 0,1,c0,80,2,0,d,f3,0,1

对比没有问题他确实没有变化,这样确切的说明了更改GLOBAL PARTITION INDEX的分区键的值不造成任何问题的原因

在于原表原数据的ROWID没有发生,而在INDEX PARATION中移动是不涉及到ROWID的。所以没有问题

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值