我在做性能优化的过程中,发现做的临时表调整操作顺序后,里面的数据没有了。
我做了一下全局事务级别的临时表定义如下:String sql = "create global temporary table "+tableName+" (CNALLBGELEMENTGUID varchar2(500),CBEGUID varchar2(500)) on commit delete rows";
后台Java代码如下:
TempTableUtil.createCTTable(tableName);
TempTableUtil.createCGroupTable(tableGroupName);
TempTableUtil.insertData(tableName, valueList);
TempTableUtil.insertData(tableGroupName, valueGroupList);
TempTableUtil.createOrgnTable(orgTableName);
我发现tableName和tableGroupName临时表批量插入的数据没有了,令我感觉非常的奇怪,于是又做了如下修改:
TempTableUtil.createCTTable(tableName);
TempTableUtil.createCGroupTable(tableGroupName);
TempTableUtil.createOrgnTable(orgTableName);
TempTableUtil.insertData(tableName, valueList);
TempTableUtil.insertData(tableGroupName, valueGroupList);
改了代码的顺序后,临时表里又有数据了,于是我怀疑可能这段代码提交触发了自动提交,导致临时表里的数据被清空了。
于是,我对Oracle的DDL和DML做了显式提交和隐式提交了解。
通常咱们做的显式提交,都需要commit才能提交事务的,对于隐式提交,不用做commit提交,会自动进行提交的。
隐式提交的定义
又名自动提交,即无需显示执行commit语句,session中的操作被自动提交到数据库的过程。
隐式提交的方式
1、正常执行完DDL语句。包括create,alter,drop,truncate,rename。
2、正常执行完DCL语句。包括grant,revoke。
3、正常退出isql*plus,没有明确发出commit或者rollback。
隐式提交的注意事项
1、执行DDL语句时,前面的DML操作也会被提交到数据库中
因为是在一个session里,那执行ddl语句的时候前面的dml语句肯定也会“不可幸免”的被提交到库中。
2、即使DDL语句执行失败,前面的DML操作也会被提交到数据库中
这就有点儿让人奇怪了,DDL都执行失败了,怎么还会提交呢?这就需要探究一下隐式提交的本质了(下文有叙述)。
3、在前面1和2的基础上,为了避免隐式提交或者回滚,尽量保证一条或者几条DML操作完成后有显示的提交或者回滚,防止后续执行的DCL或者DDL自动提交前期的DML操作。
隐式提交的本质
1、一条DDL语句执行了两次commit
commit;
DDL statement;
commit;
第一个commit将当前session中未提交的事务隐式提交,以保证DDL语句失败时的回滚位置。
第二个commit将DDL
2、为什么需要隐式提交?
为了保证事务的一致性。我们在执行DDL语句的时候,Oracle需要在它的系统表中进行元数据的记录操作(即:除了建表还会进行不少insert操作),如果它不隐式提交就无法保证一致性;从内部运行机制来看DDL语句和DML语句还是有很大区别的,DML会对每个语句的每条记录都做日志记录以便于回滚,而DDL往往没必要搞这么复杂,从功能和易用性上看隐式提交都是最好的选择。