HelloDBA [English]
搜索Internet 搜索 HelloDBABA
  Oracle技术站。email: fuyuncat@gmail.com  MSN: fuyuncat@hotmail.com   acoug  acoug 

Row Movement 对系统的影响

[English]

作者: fuyuncat

来源: www.HelloDBA.com

日期: 2009-08-28 05:57:56

分享到  新浪微博 腾讯微博 人人网 i贴吧 开心网 豆瓣 淘宝 推特 Facebook GMail Blogger Orkut Google Bookmarks

    ROW MOVEMENT特性最初是在8i时引入的,其目的是提高分区表的灵活性——允许更新Partition Key。这一特性默认是关闭,只是在使用到一些特殊功能时会要求打开。除了之前提到的更新Partition Key,还有2个要求打开的ROW MOVEMENT的功能就是flushback table和Shrink Segment。所以,只有当使用到以上3个功能特性时,ROW MOVEMENT才会真正起作用。我们如果需要知道ROW MOVEMENT会对系统产生什么影响,就只要看这3个功能使用时会产生什么影响。
 

  • Flashback Table
     

    先看Flashback Table。这一功能能帮助我们及时回滚一些误操作,防止数据意外丢失。在使用该功能之前,必须先打开ROW MOVEMENT,否则就会抛ORA-08189错误。我们看以下例子,可以说明在使用Flashback Table功能时,ROW MOVEMENT产生了什么作用:

SQL代码
  1. SQL> create table test_move as select * from dba_users;   
  2.   
  3. Table created.   
  4.   
  5. SQL> select username, rowid from test_move;   
  6.   
  7. USERNAME                       ROWID   
  8. ------------------------------ ------------------   
  9. DMP                            AAAwSfAAFAAAVlMAAA   
  10. MYTBC                          AAAwSfAAFAAAVlMAAB   
  11. CS2                            AAAwSfAAFAAAVlMAAC   
  12. TBC                            AAAwSfAAFAAAVlMAAD   
  13. WOW                            AAAwSfAAFAAAVlMAAE   
  14. REPO                           AAAwSfAAFAAAVlMAAF   
  15. ... ...   
  16. SYSTEM                         AAAwSfAAFAAAVlMAAk   
  17. OUTLN                          AAAwSfAAFAAAVlMAAl   
  18.   
  19. 38 rows selected.   
  20.   
  21. SQL> delete from test_move where username = 'MYTBC';   
  22.   
  23. 1 row deleted.   
  24.   
  25. SQL> commit;   
  26.   
  27. Commit complete.   
  28.   
  29. SQL> flashback table test_move to timestamp(systimestamp - interval '3' minute);   
  30. flashback table test_move to timestamp(systimestamp - interval '3' minute)   
  31.                 *   
  32. ERROR at line 1:   
  33. ORA-08189: cannot flashback the table because row movement is not enabled  

    此时,由于ROW MOVEMENT还未打开,命令出错。继续完成演示:

SQL代码
  1. SQL> alter table test_move enable row movement;   
  2.   
  3. Table altered.   
  4.   
  5. SQL> flashback table test_move to timestamp(systimestamp - interval '3' minute);   
  6.   
  7. Flashback complete.   
  8.   
  9. SQL> select username, rowid from test_move;   
  10.   
  11. USERNAME                       ROWID   
  12. ------------------------------ ------------------   
  13. DMP                            AAAwSfAAFAAAVlMAAB   
  14. MYTBC                          AAAwSfAAFAAAVlMAAm   
  15. CS2                            AAAwSfAAFAAAVlMAAn   
  16. TBC                            AAAwSfAAFAAAVlMAAo   
  17. WOW                            AAAwSfAAFAAAVlMAAp   
  18. REPO                           AAAwSfAAFAAAVlMAAq   
  19. ... ...   
  20. SYSTEM                         AAAwSfAAFAAAVlMABJ   
  21. OUTLN                          AAAwSfAAFAAAVlMABK   
  22.   
  23. 38 rows selected.   

    当开启ROW MOVEMENT后,表被顺利的flashback了,数据被找回。此时,再比较flashback前后记录的ROWID,大多数记录的物理位置都变化。这个过程的内部操作, 可以通过对Flashback Table做SQL Trace来进一步观察。通过Trace,我们不难发现,Flashback Table实际是通过Flashback Query将表中数据进行了一次删除、插入操作,因此ROWID会发生变化。

  • Shrink Segment

    Shrink Segment能帮助我们压缩数据段、整理数据碎片、降低高水位,以提高性能、节省空间。它也同样要求开启ROW MOVEMENT。

SQL代码
  1. SQL> select username, rowid from test_move;   
  2.   
  3. USERNAME                       ROWID   
  4. ------------------------------ ------------------   
  5. DMP                            AAAwShAAFAAAVlQAAA   
  6. MYTBC                          AAAwShAAFAAAVlQAAB   
  7. CS2                            AAAwShAAFAAAVlQAAC   
  8. TBC                            AAAwShAAFAAAVlQAAD   
  9. WOW                            AAAwShAAFAAAVlQAAE   
  10. REPO                           AAAwShAAFAAAVlQAAF   
  11. ... ...   
  12. SYSTEM                         AAAwShAAFAAAVlQAAk   
  13. OUTLN                          AAAwShAAFAAAVlQAAl   
  14.   
  15. 38 rows selected.   
  16.   
  17. SQL> delete from test_move where username = 'MYTBC';   
  18.   
  19. 1 row deleted.   
  20.   
  21. SQL> commit;   
  22.   
  23. Commit complete.   
  24.   
  25. SQL> alter table test_move disable row movement;      
  26.      
  27. Table altered.      
  28.      
  29. SQL> alter table test_move shrink space;      
  30. alter table test_move shrink space     
  31. *      
  32. ERROR at line 1:      
  33. ORA-10636: ROW MOVEMENT is not enabled      
  34.      
  35.      
  36. SQL> alter table test_move enable row movement;      
  37.      
  38. Table altered.      
  39.      
  40. SQL> alter table test_move shrink space;      
  41.      
  42. Table altered.    
  43.   
  44. SQL> select username, rowid from test_move;   
  45.   
  46. USERNAME                       ROWID   
  47. ------------------------------ ------------------   
  48. DMP                            AAAwShAAFAAAVlMAAA   
  49. CS2                            AAAwShAAFAAAVlMAAB   
  50. TBC                            AAAwShAAFAAAVlMAAC   
  51. WOW                            AAAwShAAFAAAVlMAAD   
  52. REPO                           AAAwShAAFAAAVlMAAE   
  53. ... ...   
  54. SYSTEM                         AAAwShAAFAAAVlMAAj   
  55. OUTLN                          AAAwShAAFAAAVlMAAk   
  56.   
  57. 37 rows selected.   
  58.   
  59. SQL>   

    同样,我们可以看到在Shrink后,ROWID也变化了。从对其过程的Trace来看,Shrink对数据的改变不是通过SQL实现的,而是通过更底层的函数来实现的。

    从以上分析来看,在执行上面2种操作操作后,其最大影响就是数据的ROWID会发生变化。因此,他们对我们系统的影响就仅限于那些依赖于ROWID编写的应用。例如,一个程序需要对大量数据进行处理,为了提高效率和控制进度,我们的代码会先将需要处理的数据记录的ROWID取出放入临时表中,然后再根据ROWID对数据进行分批进行处理。当ROWID被取出后,如果对表进行了上述操作,就可能会导致后依赖ROWID进行的操作发生错误。但是,这两种操作都属于维护性操作,第一种操作发生的机会非常少,从整体看,我们基本可以忽视这一操作对应用的影响;第二种操作也很少发生,并且可以在应用offline的时间进行操作,因此它的影响也是有限的。

  • 更新Partition Key

    在更新记录中的Partition Key时,可能会导致该记录超出当前所在分区的范围,需要将其转移到其他对应分区上,因此要求开启ROW MOVEMENT。

SQL代码
  1. SQL> drop table test_move;   
  2.   
  3. Table dropped.   
  4.   
  5. SQL> create table test_move   
  6.   2  partition by list (owner)   
  7.   3  (partition p1 values ('SYS'),   
  8.   4  partition p2 values ('DEMO'),   
  9.   5  partition p3 values ('SYSTEM'),   
  10.   6  partition def values (default))   
  11.   7  as select * from dba_tables;   
  12.   
  13. Table created.   
  14.   
  15. SQL> update test_move set owner='SYS' where owner='DEMO' and table_name='T_TEST';   
  16. update test_move set owner='SYS' where owner='DEMO' and table_name='T_TEST'  
  17.        *   
  18. ERROR at line 1:   
  19. ORA-14402: updating partition key column would cause a partition change   
  20.   
  21. SQL> alter table test_move enable row movement;   
  22.   
  23. Table altered.   
  24.   
  25. SQL> update test_move set owner='SYS' where owner='DEMO' and table_name='T_TEST';   
  26.   
  27. 1 row updated.    

    这一操作产生影响的特殊之处在于这是个DML操作,是和online transaction密切相关。对于这样一个UPDATE,实际上分为3步:先从原有分区将数据删除;将原数据转移到新分区上;更新数据。其影响就在于以下几个方面:

  • 一个UPDATE被分解为DELET、INSERT、UPDATE三个操作,增加了性能负担。其中,DELETE的查询条件与原UPDATE的查询条件相同,新的UPDATE的查询条件是基于INSERT生成的新的ROWID;
  • 相应的Redo Log、Undo Log会增加;
  • 如果Update语句还涉及到了Local Index的字段的话,新、旧2个分区上的Local Index都要被更新。

 

  • 结论

    目前,ROW Movement真正会其作用(ROWID变化)只是在上述3种情况下,因此,需要分析其对系统会产生多大影响,就要分析上述三种操作在你的系统中出现的频率、以及是否有应用程序依赖与ROWID实现。对于前面两种,之前说过,它们发生的概率并不高,我个人认为基本上可以忽略它们对系统的影响。而对于最后一种,需要从应用角度进行分析——Partition Key被更新的频率有多高?如果可能,最好实施一次等量负载下更细Partition Key的压力测试,通过对比分区和非分区下其产生的性能统计数据做比较,其带来的性能负载及Waits量与分区所获取的查询性能的提高相比,哪一种方式更有助于系统和应用的性能提高。

    此外,有一点希望不要产生误解,开启ROW Movement并不会导致发生Row Migration时修改记录的Rowid。

    还有一点,Row Movement会和域索引(Domain Index)产生冲突:如果表上定义了域索引,开启Row Movement就会失败;反之亦然。

  --- The End ---

Top

Copyright ©2005,HelloDBA.Com 保留一切权利

申明
by fuyuncat