CSDN博客

img biti_rainy

证明truncate发出了可观察的commit命令

发表于2004/7/9 21:11:00  5945人阅读

一般来说,我们通常认为,truncate 的伪代码是:

commit; ---------- 1
truncate;
commit; ------------ 2

那我们有个疑问,commit 1和 truncate 是不可分割的吗?具有原子性吗?那我们来看看下面的演示

session 1:
SQL> create table t as select * from all_objects where rownum < 11;

Table created.

SQL> delete from t where rownum = 1;

1 row deleted.

SQL>



session 2:

SQL> lock table t in exclusive mode;



很明显,session 2 在这里被hang住了


session 1:

SQL> create table t as select * from all_objects where rownum < 11;

Table created.

SQL> delete from t where rownum = 1;

1 row deleted.

SQL> commit;

Commit complete.

SQL>


再看 session 2

SQL> lock table t in exclusive mode;

Table(s) Locked.

SQL>


加锁成功

这时我们再在 session 1上执行delete操作

session 1:

SQL> create table t as select * from all_objects where rownum < 11;

Table created.

SQL> delete from t where rownum = 1;

1 row deleted.

SQL> commit;

Commit complete.

SQL> delete from t where rownum = 1;


这时被阻塞了


接下来我们去 session 2中去尝试truncate

session 2:

SQL> lock table t in exclusive mode;

Table(s) Locked.

SQL> truncate table t;
truncate table t
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified


SQL>

发现truncate 失败,切到 session 1 看看
SQL> create table t as select * from all_objects where rownum < 11;

Table created.

SQL> delete from t where rownum = 1;

1 row deleted.

SQL> commit;

Commit complete.

SQL> delete from t where rownum = 1;

1 row deleted.

SQL>


    发现 session 1的删除居然成功了,而session 2的truncate 却失败了。这说明,当 session 2 truncate发出commit 1 之后,还没有执行truncate,在这之前session 1的delete操作由于是被 lock table 阻塞但是时间却在 truncate 之前,所以在这个间歇中 session 抢在了前面,从而导致 truncate 失败。

    其实之所以要做这个测试,也不纯粹是无聊,是因为我们有一个程序,需要首先truncate一个表,然后另一个进程去做一些数据的操作,如果truncate失败则后续的操作就有问题,但是truncate失败却不能阻止后面的进程的操作。当时我在想能否在truncate之前使用lock  table 去加锁,直到其他进程dml完毕这个进程获得了独占表锁然后truncate,看看这样是否可行。结果很遗憾,我的测试结果发现这个想法是不大现实的。 

 


0 0

相关博文

我的热门文章

img
取 消
img