rowid可以定位到数据的物理位置,但rowid会不会改变呢?这就涉及如果在where语句中以rowid为条件是否安全的问题。
首先insert record时rowid会不会改变?显然,不会
SQL> select rowid,t.* from dept t where t.deptno=20;
ROWID DEPTNO DNAME LOC
------------------ ---------- -------------- -------------
AAAHW5AABAAAMUSAAB 20 RESEARCH DALLAS
SQL> insert into dept values(70,'test','test');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select rowid,t.* from dept t where t.deptno=20;
ROWID DEPTNO DNAME LOC
------------------ ---------- -------------- -------------
AAAHW5AABAAAMUSAAB 20 RESEARCH DALLAS
再看看删除,删除的行的rowid,并没有被物理删除,而是空在那里等待被二次使用,问题是再次使用delete遗留的空间的时机是什么,即删除了rowid后,什么时候这个rowid会再次出现呢?
SQL> create table t(x int,y char(5));
表已创建。
SQL> insert into t select rownum,'test' from dba_objects where rownum<11;
已创建10行。
SQL> commit;
提交完成。
SQL> select rowid,x,y from t;
ROWID X Y
------------------ ---------- -----
AAAHrkAABAAAMjaAAA 1 test
AAAHrkAABAAAMjaAAB 2 test
AAAHrkAABAAAMjaAAC 3 test
AAAHrkAABAAAMjaAAD 4 test
AAAHrkAABAAAMjaAAE 5 test
AAAHrkAABAAAMjaAAF 6 test
AAAHrkAABAAAMjaAAG 7 test
AAAHrkAABAAAMjaAAH 8 test
AAAHrkAABAAAMjaAAI 9 test
AAAHrkAABAAAMjaAAJ 10 test
已选择10行。
SQL> delete from t where x=7;
已删除 1 行。
插入一行x=11,y=’test’,发现之前块上空出的空间即rowid= AAAHrkAABAAAMjaAAG没有被占用
SQL> insert into t values(11,'test');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select rowid,x,y from t;
ROWID X Y
------------------ ---------- -----
AAAHrkAABAAAMjaAAA 1 test
AAAHrkAABAAAMjaAAB 2 test
AAAHrkAABAAAMjaAAC 3 test
AAAHrkAABAAAMjaAAD 4 test
AAAHrkAABAAAMjaAAE 5 test
AAAHrkAABAAAMjaAAF 6 test
AAAHrkAABAAAMjaAAH 8 test
AAAHrkAABAAAMjaAAI 9 test
AAAHrkAABAAAMjaAAJ 10 test
AAAHrkAABAAAMjaAAK 11 test
已选择10行。
再次插入一行x=12,y=’test’.发现rowid= AAAHrkAABAAAMjaAAG还没有被占用
难道rowid将永远消失吗?
SQL> insert into t values(12,'test');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select rowid,x,y from t;
ROWID X Y
------------------ ---------- -----
AAAHrkAABAAAMjaAAA 1 test
AAAHrkAABAAAMjaAAB 2 test
AAAHrkAABAAAMjaAAC 3 test
AAAHrkAABAAAMjaAAD 4 test
AAAHrkAABAAAMjaAAE 5 test
AAAHrkAABAAAMjaAAF 6 test
AAAHrkAABAAAMjaAAH 8 test
AAAHrkAABAAAMjaAAI 9 test
AAAHrkAABAAAMjaAAJ 10 test
AAAHrkAABAAAMjaAAK 11 test
AAAHrkAABAAAMjaAAL 12 test
已选择11行。
接着插入x=13,y=’’, 发现rowid= AAAHrkAABAAAMjaAAG还没有被占用,但这步很关键
SQL> insert into t values(13,'');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select rowid,x,y from t;
ROWID X Y
------------------ ---------- -----
AAAHrkAABAAAMjaAAA 1 test
AAAHrkAABAAAMjaAAB 2 test
AAAHrkAABAAAMjaAAC 3 test
AAAHrkAABAAAMjaAAD 4 test
AAAHrkAABAAAMjaAAE 5 test
AAAHrkAABAAAMjaAAF 6 test
AAAHrkAABAAAMjaAAH 8 test
AAAHrkAABAAAMjaAAI 9 test
AAAHrkAABAAAMjaAAJ 10 test
AAAHrkAABAAAMjaAAK 11 test
AAAHrkAABAAAMjaAAL 12 test
AAAHrkAABAAAMjaAAM 13
已选择12行。
接着插入x=14,y=’’, rowid= AAAHrkAABAAAMjaAAG重现江湖
SQL> insert into t values(14,'');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select rowid,x,y from t;
ROWID X Y
------------------ ---------- -----
AAAHrkAABAAAMjaAAA 1 test
AAAHrkAABAAAMjaAAB 2 test
AAAHrkAABAAAMjaAAC 3 test
AAAHrkAABAAAMjaAAD 4 test
AAAHrkAABAAAMjaAAE 5 test
AAAHrkAABAAAMjaAAF 6 test
AAAHrkAABAAAMjaAAG 14
AAAHrkAABAAAMjaAAH 8 test
AAAHrkAABAAAMjaAAI 9 test
AAAHrkAABAAAMjaAAJ 10 test
AAAHrkAABAAAMjaAAK 11 test
AAAHrkAABAAAMjaAAL 12 test
AAAHrkAABAAAMjaAAM 13
已选择13行。,
再每次插入后都dump文件发现了原因:
删除x=7的记录,该行上记录的物理地址不变,但row上删除了数据,并且标记上’D’
1 插入x=11,y=’test’时由于需要占用的空间比被删除的x=7原占用空间大,所以使用了新的块上的行
2 插入x=12,y=’test’同上
3 插入 x=13,y=’’,该记录需要占用的空间小于x=7原占用空间,但这条记录并没有插入,而是清除了物理地址
4插入 x=14,y=’’,该记录需要占用的空间小于x=7原占用空间,且row上物理地址也清除了,故rowid被重用
但一条记录的rowid会不会改变呢?我们需要探究下update时的情况,尤其是update发生行迁移的情况
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/22111412/viewspace-613487/ ,如需转载,请注明出处,否则将追究法律责任。