曾经遇到过这个问题,但是最终只是把它作为了DBMS的一种特性或者规定。现在算是找到了答案!
原来在ORACLE中,当执行DDL语句时总是需要申请一个DDL锁,以保证DDL语句执行期间,所操作对象不会被其他SESSION修改。譬如,当执行语句ALTER TABLE T时,表T将会获得一个排它的DDL锁,语句执行结束,该锁被立即释放。事实上在ORACLE中,这是通过在DDL语句前后加上隐式的COMMIT/ROLLBACK语句来实现的。用伪码表示如下:
Begin
Commit;
DDL‐STATEMENT
Commit;
Exception
When others then rollback;
End;
因此,无论执行成功与否,DDL语句总是要提交的。需要注意的是,DDL语句开始执行之前是先提交的。因此,即使DDL语句执行失败,也不会ROLLBACK掉之前的事务。
回到最初的问题。在ORACLE中,一个存储过程块被当作一个语句,如果其中使用了DDL语句,那么如果后续的执行失败,也无法ROLLBACK掉整个事务,这样无疑违反了事务的原子性。
问题得解!
原来在ORACLE中,当执行DDL语句时总是需要申请一个DDL锁,以保证DDL语句执行期间,所操作对象不会被其他SESSION修改。譬如,当执行语句ALTER TABLE T时,表T将会获得一个排它的DDL锁,语句执行结束,该锁被立即释放。事实上在ORACLE中,这是通过在DDL语句前后加上隐式的COMMIT/ROLLBACK语句来实现的。用伪码表示如下:
Begin
Commit;
DDL‐STATEMENT
Commit;
Exception
When others then rollback;
End;
因此,无论执行成功与否,DDL语句总是要提交的。需要注意的是,DDL语句开始执行之前是先提交的。因此,即使DDL语句执行失败,也不会ROLLBACK掉之前的事务。
回到最初的问题。在ORACLE中,一个存储过程块被当作一个语句,如果其中使用了DDL语句,那么如果后续的执行失败,也无法ROLLBACK掉整个事务,这样无疑违反了事务的原子性。
问题得解!