【问题标题】:How can I tell when a MySQL table was last updated?如何判断 MySQL 表上次更新的时间?
【发布时间】:2010-09-23 08:59:02
【问题描述】:

在我页面的页脚中,我想添加类似“上次更新 xx/xx/200x”的内容,此日期是某个 mySQL 表的最后一次更新时间。

最好的方法是什么?是否有检索上次更新日期的功能?每次需要这个值时我都应该访问数据库吗?

【问题讨论】:

标签: mysql sql


【解决方案1】:

和其他人一样,但我使用了一些条件,以节省时间:

SELECT
  UPDATE_TIME,
  TABLE_SCHEMA,
  TABLE_NAME
FROM
  information_schema.tables
WHERE
  1 = 1
  AND UPDATE_TIME > '2021-11-09 00:00:00'
  AND TABLE_SCHEMA = 'db_name_here'
  AND TABLE_NAME not in ('table_name_here',)
ORDER BY
  UPDATE_TIME DESC,
  TABLE_SCHEMA,
  TABLE_NAME;

【讨论】:

    【解决方案2】:

    我让它在本地工作,但不能在我的公共网站的共享主机上工作(我认为是版权问题)。

    SELECT last_update FROM mysql.innodb_table_stats WHERE table_name = 'yourTblName';
    
    '2020-10-09 08:25:10'
    

    MySQL 5.7.20-登录 Win 8.1

    【讨论】:

      【解决方案3】:

      对于最近的表更改列表,请使用:

      SELECT UPDATE_TIME, TABLE_SCHEMA, TABLE_NAME
      FROM information_schema.tables
      ORDER BY UPDATE_TIME DESC, TABLE_SCHEMA, TABLE_NAME
      

      【讨论】:

      • 为什么我所有的UPDATE_TIME 都是空的?有什么想法吗?
      • 您的 UPDATE_TIME 为空,因为您使用的是 InnoDB 而不是 MyISAM。 InnoDB 通常是更好的选择,但它不支持 UPDATE_TIME。
      • @Xaraxia 但有些不是空的,你知道为什么吗?
      • 您的表是否在某个时候从 MyISAM 转换为 InnoDB?这是我能想到的最可能的原因。
      【解决方案4】:

      a) 它将显示所有表格以及最后更新日期

      SHOW TABLE STATUS FROM db_name;
      

      然后,您可以进一步询问具体的表:

      SHOW TABLE STATUS FROM db_name like 'table_name';
      

      b) 与上面的示例一样,您不能在“Update_time”上使用排序,但可以使用 SELECT:

      SELECT * FROM information_schema.tables WHERE TABLE_SCHEMA='db_name' ORDER BY UPDATE_TIME DESC;
      

      进一步询问特定表:

      SELECT * FROM information_schema.tables WHERE TABLE_SCHEMA='db_name' AND table_name='table_name' ORDER BY UPDATE_TIME DESC';
      

      【讨论】:

        【解决方案5】:

        我在 phpMyAdmin 中按名称创建了一个列:update-at 并从我的代码 (nodejs) 中的 Date() 方法获取当前时间。对于表中的每次更改,此列都包含更改时间。

        【讨论】:

        • 欢迎来到 StackOverflow!请edit your answer 包含您使用的一些代码,以及您选择这样做的为什么的解释。这个问题差不多 11 年了,并且已经有一个被接受的、得到好评的答案。您的答案,没有一些代码或解释,可能会被否决或删除。编辑它以包含这些内容将有助于证明它在这篇文章中的位置。
        【解决方案6】:

        虽然有一个公认的答案,但我不认为这是正确的答案。这是实现所需功能的最简单方法,但即使已在 InnoDB 中启用(实际上文档告诉您仍然应该获得 NULL ...),如果您阅读 MySQL docs,即使在当前版本(8.0)中使用UPDATE_TIME 不是正确的选择,因为:

        当服务器重新启动或 表已从 InnoDB 数据字典缓存中逐出。

        如果我理解正确(现在无法在服务器上验证它),时间戳会在服务器重启后重置。

        至于真正的(而且,成本高昂)的解决方案,您有 Bill Karwin 的 solution 和 CURRENT_TIMESTAMP,我想提出一个不同的解决方案,它基于触发器(我正在使用那个)。

        您首先创建一个单独的表(或者您可能有其他一些可用于此目的的表),它将像存储全局变量(此处为时间戳)一样工作。您需要存储两个字段 - 表名(或您希望在此处保留为表 id 的任何值)和时间戳。在你拥有它之后,你应该用这个表 id + 开始日期来初始化它(NOW() 是一个不错的选择:))。

        现在,您移动到要观察的表并在插入/更新/删除之后使用此或类似过程添加触发器:

        CREATE PROCEDURE `timestamp_update` ()
        BEGIN
            UPDATE `SCHEMA_NAME`.`TIMESTAMPS_TABLE_NAME`
            SET `timestamp_column`=DATE_FORMAT(NOW(), '%Y-%m-%d %T')
            WHERE `table_name_column`='TABLE_NAME';
        END
        

        【讨论】:

          【解决方案7】:

          最简单的方法是检查磁盘上表文件的时间戳。例如,你可以在你的数据目录下查看

          cd /var/lib/mysql/<mydatabase>
          ls -lhtr *.ibd
          

          这应该首先为您提供所有表格的列表,其中包含上次修改表格时最旧的时间。

          【讨论】:

          • 非常好的答案,因为在我的 (MariaDb) 案例中,所有表的 UPDATE_TIME 都是 NULL
          • ibd 文件只存储表结构。默认情况下,数据存储在 ibdata1 中,因此当表中的数据发生更改时,ibd 文件时间戳不会更新。 https://dev.mysql.com/doc/refman/8.0/en/show-table-status.html
          • @StackUnderflow,你说的不准确。 ibd 文件存储包含一个或多个表的表空间的数据和索引。如果数据存储在 ibdata1 中,则不会有 ibd 文件。自 2013 年 MySQL 5.6 以来,将数据存储在每个表一个文件中一直是默认设置。
          【解决方案8】:

          我很惊讶没有人建议跟踪每行的最后更新时间:

          mysql> CREATE TABLE foo (
            id INT PRIMARY KEY
            x INT,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP 
                               ON UPDATE CURRENT_TIMESTAMP,
            KEY (updated_at)
          );
          
          mysql> INSERT INTO foo VALUES (1, NOW() - INTERVAL 3 DAY), (2, NOW());
          
          mysql> SELECT * FROM foo;
          +----+------+---------------------+
          | id | x    | updated_at          |
          +----+------+---------------------+
          |  1 | NULL | 2013-08-18 03:26:28 |
          |  2 | NULL | 2013-08-21 03:26:28 |
          +----+------+---------------------+
          
          mysql> UPDATE foo SET x = 1234 WHERE id = 1;
          

          这会更新时间戳,即使我们没有在 UPDATE 中提及它。

          mysql> SELECT * FROM foo;
          +----+------+---------------------+
          | id | x    | updated_at          |
          +----+------+---------------------+
          |  1 | 1235 | 2013-08-21 03:30:20 | <-- this row has been updated
          |  2 | NULL | 2013-08-21 03:26:28 |
          +----+------+---------------------+
          

          现在您可以查询 MAX():

          mysql> SELECT MAX(updated_at) FROM foo;
          +---------------------+
          | MAX(updated_at)     |
          +---------------------+
          | 2013-08-21 03:30:20 |
          +---------------------+
          

          诚然,这需要更多存储空间(TIMESTAMP 每行 4 个字节)。
          这适用于 5.7.15 版本的 MySQL 之前的 InnoDB 表INFORMATION_SCHEMA.TABLES.UPDATE_TIME 不适用。

          【讨论】:

          • +1 就我而言,这是这个问题的唯一正确答案。这个问题真的想知道何时更新相关数据,而不是何时更新表(与用户无关)可能会或可能不会因任何原因而更改。
          • 但是如果你删除一条更新时间较短的记录,MAX(updated_at)就不起作用了。
          • @Ammamon,是的,如果您还需要考虑删除,此解决方案不会反映这一点。更新汇总表的触发器可能是唯一全面的解决方案,但这会造成瓶颈。
          • 对于大多数情况下,知道删除不会那么相关,并且许多更高级别的应用程序不会真正从许多表中删除,而只是取消设置等效项的标志。
          • @Pavan,没有区别,您只是依赖默认行为,我的示例明确说明了该选项。但该选项与默认行为相同。
          【解决方案9】:

          操作系统级别分析:

          查找数据库在磁盘上的存储位置:

          grep datadir /etc/my.cnf
          datadir=/var/lib/mysql
          

          检查最近的修改

          cd /var/lib/mysql/{db_name}
          ls -lrt
          

          应该适用于所有数据库类型。

          【讨论】:

            【解决方案10】:

            这就是我所做的,我希望它有所帮助。

            <?php
                mysql_connect("localhost", "USER", "PASSWORD") or die(mysql_error());
                mysql_select_db("information_schema") or die(mysql_error());
                $query1 = "SELECT `UPDATE_TIME` FROM `TABLES` WHERE
                    `TABLE_SCHEMA` LIKE 'DataBaseName' AND `TABLE_NAME` LIKE 'TableName'";
                $result1 = mysql_query($query1) or die(mysql_error());
                while($row = mysql_fetch_array($result1)) {
                    echo "<strong>1r tr.: </strong>".$row['UPDATE_TIME'];
                }
            ?>
            

            【讨论】:

            • 为什么要在这里使用?
            • @WesleyMurch: 标签已被弃用。
            【解决方案11】:

            我没有information_schema数据库,使用的是mysql 4.1.16版本,所以这种情况下可以这样查询:

            SHOW TABLE STATUS FROM your_database LIKE 'your_table';
            

            它将返回这些列:

            |姓名 |引擎 |版本 |行格式 |行 |平均行长度
            |数据长度 |最大数据长度 |索引长度 |数据免费 |自动增量
            |创建时间 | 更新时间 |检查时间 |整理
            |校验和 |创建选项 |评论 |

            如您所见,有一个名为“Update_time”的列显示了your_table的最后更新时间。

            【讨论】:

            • 它的执行速度也比 SELECT 语句快(4 倍)
            • 事实上,大多数像这样的 SHOW 命令只是在内部映射到 Information_schema 查询,所以这个答案给出的数据与上面 Alnitak 的答案完全相同。 ajacian81 是正确的——它不适用于 MySQL 的默认存储引擎 InnoDB。
            【解决方案12】:

            不确定这是否会引起兴趣。在 mysql 和客户端之间使用 mysqlproxy,并使用 lua 脚本根据有趣的表更改更新 memcached 中的键值 UPDATE、DELETE、INSERT 是我最近所做的解决方案。如果包装器支持 php 中的钩子或触发器,这可能会更容易。到目前为止,没有一个包装器这样做。

            【讨论】:

              【解决方案13】:

              在更高版本的 MySQL 中,您可以使用 information_schema 数据库来告诉您何时更新了另一个表:

              SELECT UPDATE_TIME
              FROM   information_schema.tables
              WHERE  TABLE_SCHEMA = 'dbname'
                 AND TABLE_NAME = 'tabname'
              

              这当然意味着打开与数据库的连接。


              另一种选择是在 MySQL 表更新时“触摸”特定文件:

              关于数据库更新:

              • O_RDRW 模式打开您的时间戳文件
              • close又来了

              或者

              • 使用touch(),PHP 等效于utimes() 函数,更改文件时间戳。

              页面显示:

              • 使用stat()回读文件修改时间。

              【讨论】:

              • 有关 InnoDB 限制的详细信息,请参阅dev.mysql.com/doc/refman/5.5/en/show-table-status.htmlshow table status 使用 information_schema.tables
              • 下面的UPDATE_TIME 方法和show table status 方法仅适用于MyISAM 引擎,不适用于InnoDB。虽然这被列为bug,但在MySQL 5.5 Reference中也有提及,这也表示file_per_table模式是修改时间的不可靠指标。
              • 再一次,在 InnoDB 上不起作用,因为 mysql 是他妈的错误:bugs.mysql.com/bug.php?id=14374
              • 对于 MySQL 5.7.2+ 它还 works for InnoDB:“从 MySQL 5.7.2 开始,UPDATE_TIME 显示在未分区的 InnoDB 表上执行的最后一次 UPDATE、INSERT 或 DELETE 的时间戳值. 以前,UPDATE_TIME 为 InnoDB 表显示 NULL 值。"
              • 这对我来说似乎在重新启动时不会持续存在(在 5.7.11 版上)。
              【解决方案14】:

              如果您运行的是 Linux,您可以使用 inotify 查看表或数据库目录。 inotify 可从 PHP、node.js、perl 获得,我怀疑大多数其他语言。当然,您必须安装 inotify 或让您的 ISP 安装它。很多 ISP 不会。

              【讨论】:

              • 如果您的数据库在单独的服务器上运行,文件系统检查将没有用处
              【解决方案15】:

              只需从文件系统中获取修改的文件日期。用我的语言是:

               tbl_updated = file.update_time(
                      "C:\ProgramData\MySQL\MySQL Server 5.5\data\mydb\person.frm")
              

              输出:

              1/25/2013 06:04:10 AM
              

              【讨论】:

              • 看起来像高度不可移植的黑客,一个可以在任何地方工作的标准方法会更好
              【解决方案16】:

              我会创建一个触发器来捕获所有更新/插入/删除并在自定义表中写入时间戳,例如 表名 |时间戳

              只是因为我不喜欢直接读取数据库服务器内部系统表的想法

              【讨论】:

              • 这对于 MS SQL 来说似乎是一个很好的解决方案,因为没有像 MySQL 中那样的 UPDATE_TIME 列。
              【解决方案17】:

              当查询不可用时将查询缓存在全局变量中。

              创建一个网页以在更新时强制重新加载缓存。

              在您的部署脚本中添加对重新加载页面的调用。

              【讨论】:

              • 在没有外部帮助的情况下,您不能在 PHP 页面的独立调用之间“缓存”变量。
              猜你喜欢
              • 2012-05-02
              • 2020-01-08
              • 2010-09-20
              • 2014-06-27
              • 1970-01-01
              • 2016-08-18
              • 1970-01-01
              • 2010-09-18
              相关资源
              最近更新 更多