Oracle中truncate表不更新last_ddl_time列

 

 

Oracle中truncate表不更新last_ddl_time列

问题描述

最近发现数据库中定时job的某张表,每天都有truncate动作,由于调整了job的interval时间,想查看last_ddl_time辅助验证job的运行情况,结果发现last_ddl_time是几天前的时间。

单单从这点上看我还以为这个job没运行过,但是从last_date字段又可以看出最近的时间是执行过的,怎么回事呢?

测试分析

由于表示临时用的表,而且是一张空表,征得相关人员许可后,测试环境中(存在同样的问题)对表手工做truncate,再次查看last_ddl_time,果然没变化。

开始mos找资料,有这样一篇文章“LAST_DDL_TIME Not Changing (Doc ID 1448241.1)”,里边这样描述:

10g and subsequent do not invalidate dependent objects unnecessarily. Therefore, since the PACKAGE BODY is not changing, the LAST_DDL_TIME does not change.

If you would change something in the package body (a line of code, not simply a comment), you will find that LAST_DDL_TIME changes.

LAST_DDL_TIME changes for CREATE OR REPLACE ...

1. When the source of the procedure changes.
... OR ...
2. The settings of following parameters change from original creation time:
plsql_optimize_level, plsql_code_type, plsql_debug, nls_length_semantics, plsql_warnings, plsql_ccflags, plsql_compiler_flags.

So, this is not a bug, but expected behavior. Last_ddl_time is only updated if the object actually changes.

虽然DOC上描述的场景和我遇到的情况不一样,不过里边有句话提醒了我。

If you would change something in the package body (a line of code, not simply a comment), you will find that LAST_DDL_TIME changes.

(如果您要更改程序包主体中的某些内容(一行代码,而不仅仅是注释),则会发现LAST_DDL_TIME发生了更改。)

So, this is not a bug, but expected behavior. Last_ddl_time is only updated if the object actually changes.

(因此,这不是错误,而是预期的行为。仅当对象实际更改时,Last_ddl_time才会更新。)

所以有可能是原表就是空表,你做truncate操作的时候,实际上就不会更新last_ddl_time这个列。

测试模拟

[oracle@oracle ~]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Tue Apr 28 08:34:31 2020

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

Connected to an idle instance.

SYS@zkm> startup;
ORACLE instance started.

Total System Global Area  784998400 bytes
Fixed Size                  2257352 bytes
Variable Size             465571384 bytes
Database Buffers          314572800 bytes
Redo Buffers                2596864 bytes
Database mounted.
Database opened.

SYS@zkm> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

Session altered.

SYS@zkm> select last_ddl_time from dba_objects where object_name='TEST';

LAST_DDL_TIME
-------------------
2020-04-26 10:37:05

SYS@zkm> !date
Tue Apr 28 08:35:27 CST 2020

SYS@zkm> desc zkm.test
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER

SYS@zkm> delete from zkm.test;

13107200 rows deleted.

SYS@zkm> commit;

Commit complete.

SYS@zkm> truncate table zkm.test;

Table truncated.

SYS@zkm> select last_ddl_time from dba_objects where object_name='TEST';

LAST_DDL_TIME
-------------------
2020-04-28 08:43:24

从这里看,我将表的数据全部delete并且commit后,truncate表竟然last_ddl_time更新了。

随后我想到truncate表实际上是换了个段,data_object_id会变,那再次truncate的话应该不会再更新last_ddl_time了。

SYS@zkm> select object_id,data_object_id from dba_objects where owner='ZKM' and object_name='TEST';

 OBJECT_ID DATA_OBJECT_ID
---------- --------------
     18815          18832

SYS@zkm> truncate table zkm.test;

Table truncated.

SYS@zkm> select last_ddl_time from dba_objects where object_name='TEST';

LAST_DDL_TIME
-------------------
2020-04-28 08:43:24

SYS@zkm> select object_id,data_object_id from dba_objects where owner='ZKM' and object_name='TEST';

 OBJECT_ID DATA_OBJECT_ID
---------- --------------
     18815          18832

果然是这样,而且data_object_id也没变了。

原文地址:https://www.cnblogs.com/PiscesCanon/p/12791854.html