【问题标题】:Where does MYSQL store logic for "UPDATE CURRENT_TIMESTAMP"MYSQL 在哪里存储“UPDATE CURRENT_TIMESTAMP”的逻辑
【发布时间】:2021-07-01 13:31:19
【问题描述】:

我通常会从 PHP 更新时间戳列,但我意识到这可以在 MySQL DBMS 级别完成。所以我通过我用于数据库管理员的 SQLYog 找到并测试了下面的代码:

 CREATE TABLE `TestLastUpdate` (
`ID` INT NULL,
`Name` VARCHAR(50) NULL,
`Address` VARCHAR(50) NULL,
`LastUpdate` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
COMMENT='Last Update'
;

表已按预期创建,每次更新字段时 LastUpdate 都会更改。

但是,我无法在表信息中找到任何内容来显示它的存储位置(我知道 current_timestamp() 可以正常用于插入),该代码也没有创建触发器或事件。

那么这个逻辑存储在哪里?我想还有一些其他的表属性(除了外键、索引)是 MySQL 保留但 SQLYog 不显示的?

【问题讨论】:

  • 我不明白你的意思。它只是在内部(mysql 服务器)获取时间戳的值并在表字段中更新它。这有什么问题?

标签: mysql sqlyog


【解决方案1】:

您可以在 INFORMATION_SCHEMA 中看到时间戳列的这些属性:

mysql> create table test.mytable (id serial primary key, ts timestamp default current_timestamp on update current_timestamp);
mysql> select table_name, column_name, column_default, extra from information_schema.columns where table_name='mytable';
+------------+-------------+-------------------+-----------------------------+
| table_name | column_name | column_default    | extra                       |
+------------+-------------+-------------------+-----------------------------+
| mytable    | id          | NULL              | auto_increment              |
| mytable    | ts          | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+------------+-------------+-------------------+-----------------------------+

在 MySQL 8.0 之前的版本中,所有表元数据都在与您的表对应的 .frm 文件中。

$ ls -l /usr/local/var/mysql/test
total 256
-rw-r-----  1 bkarwin  admin      67 Jun 16 10:04 db.opt
-rw-r-----  1 bkarwin  admin    8582 Jul  1 07:05 mytable.frm
-rw-r-----  1 bkarwin  admin  114688 Jul  1 07:05 mytable.ibd

.frm 文件中,有一个名为unireg_check 的位字段用于存储列的属性。一些位是:

  • TIMESTAMP_DN_FIELD - 列定义DEFAULT CURRENT_TIMESTAMP
  • TIMESTAMP_UN_FIELD - 列定义ON UPDATE CURRENT_TIMESTAMP
  • TIMESTAMP_DNUN_FIELD - 该列是 用两个属性定义
  • NONE - 该列未定义任何属性

如何使用这些位?这深埋在 MySQL 源代码中。都是特例代码。

https://github.com/mysql/mysql-server/blob/5.7/sql/sql_table.cc#L7822-L7844

/*
   Set CURRENT_TIMESTAMP as default/update value based on
   the unireg_check value.
*/

if ((def->sql_type == MYSQL_TYPE_DATETIME ||
     def->sql_type == MYSQL_TYPE_TIMESTAMP)
    && (def->unireg_check != Field::NONE))
{
  Item_func_now_local *now = new (thd->mem_root) Item_func_now_local(0);
  if (!now)
    DBUG_RETURN(true);

  if (def->unireg_check == Field::TIMESTAMP_DN_FIELD)
    default_value= now;
  else if (def->unireg_check == Field::TIMESTAMP_UN_FIELD)
    update_value= now;
  else if (def->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
  {
    update_value= now;
    default_value= now;
  }
}

这是前工程总监 Stewart Smith 的一篇文章,描述了 .frm 文件的这种用法:https://planet.mysql.com/entry/?id=17539

您可能想知道,“什么是 unireg?”它是由 MySQL 创始人 Michael Widenius 开发的数据库管理系统。 Unireg 可以追溯到 1979 年(参见 https://exadel.com/news/old-reliable-mysql-history/)。 .frm 文件的设计借鉴了旧的 Unireg 项目的代码,根据 Stewart 的博客,甚至有一些 unireg_check 位域在 MySQL 中未使用但被 Unireg 使用。

在某些方面,MySQL — 就像许多软件一样 — 就像一座建在一座被毁的罗马城堡的基础上的摩天大楼。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 2015-10-25
    • 1970-01-01
    相关资源
    最近更新 更多