非分区键的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/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/7728585/viewspace-1673529/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值