这里说的CREATE_TIME和UPDATE_TIME是information_schema.tables中的CREATE_TIME和UPDATE_TIME,那么CREATE_TIME能代表建表时间吗?UPDATE_TIME能代表最后修改时间嘛?我们分别进行讨论。
一、CREATE_TIME
从定义来看它好像表示的是表的建立时间,但是实际上并不是,我们分5.7和8.0进行讨论。
5.7中的CREATE_TIME
在5.7中CREATE_TIME取自frm文件的ctime(inode信息修改的时间),其中我们的一个文件包含3个时间,
- Access(atime):访问时间,比如常见的read()就会修改这个时间,但是由于现代Linux一般使用MS_REATIME挂在文件系统,因此只有当Access小于等于Modify时间的时候才会进行修改,或者24小时未修改访问时间才会修改,这主要是为了提高性能。
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
这里的relatime就是这样一个标记。
- Modify(mtime):文件内容的修改时间,比如常见的write()、truncate()、utime()操作就会修改这个时间。
- Change(ctime):inode信息修改的时间,inode中包含了一些管理信息比如,文件类型、文件用户和属组、硬连接数量、文件大小、文件类型等,那么比如chown()、chmod()、write()、truncate()、utime()、rename()等操作都会导致这个时间的更改。
那么正常情况下,任何涉及到frm重建的DDL语句都会导致CREATE_TIME改变,比如增加字段、增加索引、重建表等操作因为这些操作连frm文件都新建过了,如下,

而对于rename table的操作,因为涉及到rename()操作因此,也会改变CREATE_TIME,

那么我们理解为常见的DDL都会导致这个时间更改除此之外,任何对frm文件的授权、复制等物理操作都会导致这个时间的改变,下面我们简单测试一下,我们这里就使用chown授权操作,

OS操作如下,

因此5.7中的CREATE_TIME并不能代表的建立时间,主要影响它的因素有:
- DDL操作新建和重名了FRM文件,重命名可以考虑为OS影响。
- OS操作对FRM文件进行了授权和拷贝操作等。
8.0中的CREATE_TIME
到了8.0已经没有FRM文件了,而取代它的是存储在mysql数据库下面的tables表的created,但是这个只能在DEBUG环境下通过下面方式获取,
SET session debug='+d,skip_dd_table_access_check';
当我们查看 show create table information_schema.tables \G的时候会发现tbl.created AS CREATE_TIME,那么这个问题就是mysql.tables的created字段什么时候更改,其实这个更改就像5.7的DDL部分一样,只要涉及到需要重建FRM文件的DDL都会导致created时间的更改,但是好在任何OS的操作不会影响到这个信息,并且rename table也不会影响,如下,

比如新建字段、新加索引、重建表都会导致这个时间更改,但是rename table操作在5.7中因为是rename()操作导致frm ctime信息的更改,但是8.0就不存在这个问题了。因此8.0中的CREATE_TIME并也不能代表的建立时间,主要影响它的因素只有常见的DDL操作了。
二、UPDATE_TIME
这个就比较简单了,在5.7和8.0都代表是最后一次修改表记录的时间 ,这里是数据的最后修改时间(update/insert/delete),但是看5.7起来它并不持久化,因此重启后可能为NULL,而8.0的缓存部分已经持久化到表mysql.table_stats(debug版本)中了,但是最新的值也不会持久化。
其主要修改的函数是trx_update_mod_tables_timestamp,其在事务提交的时候触发修改,但是在8.0 由于information_schema_stats_expiry的影响可能获取的并不是最新的,要查看最新的可以考虑如下访问,

官方文档也有描述如下,
