【IT168 服务器学院】 Ask Tom 之中英对照20051213——使用rowid定位行是否可靠
Alexander
使用rowid定位行是否可靠
版本9.2.0
原提交于美国东部时间2005年12月12日11:15,最新更新于2005年12月12日16:13
问:
你好Tom,
我在看一个客户端应用,它需要取包括ROWID在内的若干列,然后用ROWID来定位需要更新的行。
update some_table t set col1=value1
where t.rowid = :selected_rowid
这样做安全么?如果表被修改过,一行的ROWID会改变么?
我做了一些研究:
create table a(i number, c varchar2(250));
insert into a select some_numeric_column, ''a'' from table_500K_rows;
commit;
select rowid r,i,c from a where rownum<100;
然后我修改几行:
update a
set c='';asdfha sdfhaj sdhf asdhlf asldfh ajlskdfh jklasdh fjasdhf jlaksh dfjlashdfjashdfa sdjklfhalsdfhajlsdhflashdflasdhflasd''
where i<200;
commit;
然后重复如下的select:
select rowid r,i,c from a where rownum<100;
我得到了不同的行,所以我猜想我将c更新为一个大值时分割了页,但rowid保留未变:
select rowid r,i,c from a where i<100
返回了相同的行和相同的rowid。ROWID会改变么?如果是,我如何简单的再现?
谢谢你。
答:
一个rowid在插入时分配给一行,除非该行被删除并重新插入(就是说它是另一行,不再是原来那行了),rowid会保持不变。
但是如果DBA或表的所有者设置了表的"enable row movement"属性,行可能被多个命令“透明的”删除+插入。
就是说,
如果你更新分区关键字会导致行从一个分区转移到另一个分区,分区表中的行的rowid会改变。
如果你使用了alter table t shrink space compact,rowid会改变
如果你使用了alter table t move,rowid会改变
如果你使用了flashback table t to ....,rowid会改变
但是如果你将rowid和主键一起使用,那在任何情况下都是十分安全的:
update t
set...
where rowid = :x and primary_key = :pk;
我们可以使用rowid来找到行(速度快),认为它还在那里并更新它。注意,你还是需要考虑结合对更新丢失的保护!!!你不能只是用rowid和主键来修改——除非你在读出行时锁住它,否则你将覆盖其他用户的更新。
--------------------------------------------------------------------------------
评论
Single update statement? December 12, 2005
评论者:Greg来自多伦多
Tom,对于单一一条update语句这也是个问题么?
例如:
Update some_table
set value = something
where rowid in ( select rowid from some_table where some_critieria);
仅一条语句?Rollback/Undo将为我们保留记录,是么?这里rowid是“安全”的吧。
回复:
in this case rowid is "safe" but perhaps not "efficient"
这里rowid是“安全”的,但可能不是“高效”的。
update t
set value = something
where some_criteria;
除非子查询有分析(analytics)或类似的东西……
What about page splits? December 12, 2005
评论者:Alexander来自芝加哥
Tom,
谢谢你的解释。
当我更新窄行,将c设为更宽的值时,发生了哪些(操作)?有页分割么?如果页被分割了,ROWID没有改变,那ROWID内在含义究竟是什么?
回复:
行迁移。
在本站搜索"row migration",或者看看Expert one on one Oracle或Oracle: Database Architecture,我详细的进行了讲解。
即便行迁移了,ROWID是不变的。
Different row, same rowid December 12, 2005
评论者:一个读者来自加州圣弗朗西斯科
ROWID在如下情况中也是不可靠的。
会话1: 获取一行和rowid X
会话2:删除rowid X的行,提交
/* rowid X 此时可以自由重用 */
会话3: 插入rowid为X的新行,提交
会话1: update .... where rowid = X
会话1的更新不是更新早前取出的同一行了。
回复:
这就是为什么我上面提到需要主键。
....
但是如果你将rowid和主键一起使用,那在任何情况下都是十分安全的
.....
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
原文标题:
Alexander -- Thanks for the question regarding "Is it safe to use ROWID to locate a row?", version 9.2.0
原文地址:
http://asktom.oracle.com/pls/ask ... AYID:53140678334596
--------------------------------------------------------------------------------
原文版权归属asktom.oracle.com所有,翻译 by ern·CNOUG
2005-12-13 09:49:00