彻底理解move 操作

前几天群里有人问,move 操作,我这里做了几个实验,方便大家了解move 的基本操作。
(1)  oracle 的move 操作,rowid 如何变化?
SQL> drop  table daodao;

表已删除。

SQL> create table daodao (id int, name char(2000)) tablespace users;

表已创建。

SQL> insert into daodao values (1,'aa');

已创建 1 行。

SQL> insert into daodao values (2,'bb');

已创建 1 行。

SQL> insert into daodao values (3,'cc');

已创建 1 行。

SQL> insert into daodao values (4,'dd');

已创建 1 行。

SQL> insert into daodao values (5,'ee');

已创建 1 行。

SQL> insert into daodao values (6,'ff');

已创建 1 行。

SQL> insert into daodao values (7,'gg');

已创建 1 行。

SQL> insert into daodao values (8,'hh');

已创建 1 行。

SQL> insert into daodao values (9,'ii');

已创建 1 行。

SQL> insert into daodao values (10,'jj');

已创建 1 行。

SQL> commit;

提交完成。

SQL> select rowid from daodao;

ROWID
------------------
AAur6aAAFAAC2/lAAA
AAur6aAAFAAC2/lAAB
AAur6aAAFAAC2/lAAC
AAur6aAAFAAC2/mAAA
AAur6aAAFAAC2/mAAB
AAur6aAAFAAC2/mAAC
AAur6aAAFAAC2/nAAA
AAur6aAAFAAC2/nAAB
AAur6aAAFAAC2/nAAC
AAur6aAAFAAC2/oAAA

已选择10行。

SQL> select Dbms_Rowid.rowid_block_number(rowid)  from daodao;

DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------
                              749541
                              749541
                              749541
                              749542
                              749542
                              749542
                              749543
                              749543
                              749543
                              749544

已选择10行。

SQL> delete from daodao where mod(id,2)=1;

已删除5行。

SQL> select Dbms_Rowid.rowid_block_number(rowid)  from daodao;

DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------
                              749541
                              749542
                              749542
                              749543
                              749544

SQL> alter table daodao move;

表已更改。

SQL> select Dbms_Rowid.rowid_block_number(rowid)  from daodao;

DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------------------------
                              749548
                              749548
                              749548
                              749549
                              749549

SQL> select id,Dbms_Rowid.rowid_block_number(rowid)  from daodao;

        ID DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
         2                               749548
         4                               749548
         6                               749548
         8                               749549
        10                               749549

move操作后,数据的rowid发生了改变,我们知道,index是通过rowid来fetch数据行的,所以,table上的index是必须要rebuild的。

(2)  move 操作索引会失效
SQL> create index daodao_index on daodao(id);

索引已创建。

SQL> alter table daodao move;

表已更改。

SQL> select id,Dbms_Rowid.rowid_block_number(rowid)  from daodao;

        ID DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
---------- ------------------------------------
         2                               749540
         4                               749540
         6                               749540
         8                               749541
        10                               749541

SQL> select index_name,status from user_indexes where index_name='DAODAO_INDEX';


INDEX_NAME                     STATUS
------------------------------ --------
DAODAO_INDEX                   UNUSABLE

从这里可以看到,当daodao进行move操作后,该table 上的inedx的状态为UNUSABLE,这时,我们可以使用alter index daodao_index rebuild online的命令,
进行在线rebuild。

(3) move 操作的锁问题

另外当我们对表进行move 的时候,需要加锁,我们可以看下
建立一个大表:
SQL> create table daodao_big as select a.* from  dba_objects a, (select * from dba_objects b where rownum <200)b;

Table created.

SQL> alter table daodao_big move;

打开另外一个会话,可以看到:



SQL> SELECT b.session_id AS sid,
  2         NVL(b.oracle_username, '(oracle)') AS username,
  3         a.owner AS object_owner,
  4         a.object_name,
  5         Decode(b.locked_mode, 0, 'None',
  6                               1, 'Null (NULL)',
  7                               2, 'Row-S (SS)',
  8                               3, 'Row-X (SX)',
  9                               4, 'Share (S)',
 10                               5, 'S/Row-X (SSX)',
 11                               6, 'Exclusive (X)',
 12                               b.locked_mode) locked_mode,
 13         b.os_user_name
 14  FROM   dba_objects a,
 15         v$locked_object b
 16  WHERE  a.object_id = b.object_id;

       SID USERNAME                       OBJECT_OWNER
---------- ------------------------------ ------------------------------
OBJECT_NAME
--------------------------------------------------------------------------------
LOCKED_MODE                              OS_USER_NAME
---------------------------------------- ------------------------------
       159 SYS                            SYS
DAODAO_BIG
Exclusive (X)                            oracle


这里是6号锁,独占锁.

这就意味着,table在进行move操作时,我们只能对它进行select的操作。反过来说,当我们的一个session对table进行DML操作且没有commit时,
在另一个session中是不能对这个table进行move操作的,否则oracle会返回这样的错误信息:ORA-00054

(4)  现在来看下move 能否降低高水位?

SQL> create table dd_hwm as select * from dba_objects;

Table created.


SQL> show user;
USER is "SYS"

SQL> exec show_space('DD_HWM');

PL/SQL procedure successfully completed.

SQL> set serverout on;
SQL> exec show_space('DD_HWM');
Free Blocks.............................               0
Total Blocks............................             768
Total Bytes.............................       6,291,456
Total MBytes............................               6
Unused Blocks...........................              69
Unused Bytes............................         565,248
Last Used Ext BlockId...................          63,369
Last Used Block.........................              59

PL/SQL procedure successfully completed.

SQL> desc dba_segments;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 OWNER                                              VARCHAR2(30)
 SEGMENT_NAME                                       VARCHAR2(81)
 PARTITION_NAME                                     VARCHAR2(30)
 SEGMENT_TYPE                                       VARCHAR2(18)
 TABLESPACE_NAME                                    VARCHAR2(30)
 HEADER_FILE                                        NUMBER
 HEADER_BLOCK                                       NUMBER
 BYTES                                              NUMBER
 BLOCKS                                             NUMBER
 EXTENTS                                            NUMBER
 INITIAL_EXTENT                                     NUMBER
 NEXT_EXTENT                                        NUMBER
 MIN_EXTENTS                                        NUMBER
 MAX_EXTENTS                                        NUMBER
 PCT_INCREASE                                       NUMBER
 FREELISTS                                          NUMBER
 FREELIST_GROUPS                                    NUMBER
 RELATIVE_FNO                                       NUMBER
 BUFFER_POOL                                        VARCHAR2(7)


SQL> select header_file,header_block from dba_segments where segment_name ='DD_HWM';

HEADER_FILE HEADER_BLOCK
----------- ------------
          1       175449

SQL> alter system dump datafile 1 block 175449;

System altered.

SQL> select get_trace from dual;

GET_TRACE
--------------------------------------------------------------------------------
/u01/app/oracle/admin/huangchao/udump/huangchao_ora_13180.trc


SQL> !cat /u01/app/oracle/admin/huangchao/udump/huangchao_ora_13180.trc| grep Highwater
      Highwater::  0x0040f7c4  ext#: 20     blk#: 59     ext size: 128   

!cat /u01/app/oracle/admin/huangchao/udump/huangchao_ora_13180.trc| grep below
  #blocks below: 698 


SQL> select get_fb('0x0040f7c4') from dual;

GET_FB('0X0040F7C4')
--------------------------------------------------------------------------------
datafile# is:1
datablock is:63428
dump command:alter system dump datafile 1 block 63428;


SQL> delete from dd_hwm where rownum <20000;

19999 rows deleted.

SQL> commit;

Commit complete.

SQL> alter table dd_hwm move;

Table altered.

SQL> exec show_space('DD_HWM');
Free Blocks.............................               0
Total Blocks............................             512
Total Bytes.............................       4,194,304
Total MBytes............................               4
Unused Blocks...........................              79
Unused Bytes............................         647,168
Last Used Ext BlockId...................          63,881
Last Used Block.........................              49

PL/SQL procedure successfully completed.


SQL> select header_file,header_block from dba_segments where segment_name ='DD_HWM';

HEADER_FILE HEADER_BLOCK
----------- ------------
          1       178985    -- 从这里看段头发生改变

SQL> alter system dump datafile 1 block 178985;

System altered.

SQL> !cat /u01/app/oracle/admin/huangchao/udump/huangchao_ora_13180.trc| grep Highwater
      Highwater::  0x0040f7c4  ext#: 20     blk#: 59     ext size: 128    
      Highwater::  0x0040f9ba  ext#: 18     blk#: 49     ext size: 128   

SQL> select get_fb('0x0040f9ba') from dual;

GET_FB('0X0040F9BA')
--------------------------------------------------------------------------------
datafile# is:1
datablock is:63930
dump command:alter system dump datafile 1 block 63930;

SQL> !cat /u01/app/oracle/admin/huangchao/udump/huangchao_ora_13180.trc| grep below
  #blocks below: 698   --  第一次的高水位下的块  
  #blocks below: 432   --  第二次的高水位下管理的块

table的HWM降低了!


我们还可以使用别的方法来降低table的HWM,比如shrink,CTAS 等操作,其实到现在可以看出move操作也可以用来解决table中的行迁移的问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值