记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

开心一刻

我妻子痛经了,正躺在沙发上。她两岁的女儿看着她问。

[En]

My wife had dysmenorrhea and was lying on the sofa. Her two-year-old daughter looked at her and asked.

女儿:妈妈,你怎么了

老婆:妈妈肚子痛

女儿:哦,妈妈你头疼

妻子:这不是头疼。妈妈肚子疼。

[En]

Wife: it’s not a headache. Mom has a stomachache.

女儿用她的不锈钢饭碗打妻子的额头,说:妈妈,哪里疼?

[En]

The daughter hit her wife on the forehead with her stainless steel rice bowl and said, Mom, where does it hurt?

老婆:头疼,头疼

我的妻子痛苦地看着我说:“这个女孩可以做任何你想做的事,也可以跟着我。”

[En]

My wife looked at me bitterly and said, “this girl can do whatever you want or follow me.”

我低下头,低声说:“我被你欺负了。你想要谁当女孩?”

[En]

I bowed my head and whispered, “I’ve been bullied by you. Who do you want to be a girl?”

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

问题背景

需求背景

需求:控制商品上下架,下架商品不能卖。

[En]

Demand: control the goods on and off the shelves, and the goods off the shelves cannot be sold.

上架与下架的管控,在我负责的项目(单据系统)中实现;销售的控制则是在另外一个项目(POS系统)中实现

POS系统定时的从单据系统中拉取数据,并对商品的销售进行控制

MySQL 版本: 5.7.20 -log

单据系统设计了两张表:

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知
DROP TABLE IF EXISTS t_ware_on_off_bill;
CREATE TABLE t_ware_on_off_bill (
  id BIGINT(19) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  bill_code VARCHAR(45) NOT NULL COMMENT '单据编号',
  bill_type TINYINT(2) NOT NULL DEFAULT 1 COMMENT '单据类型(1=下架,2=上架)',
  bill_status TINYINT(2) NOT NULL COMMENT '单据状态(1=草稿,2=已提交,3=审核中,4=已生效,5=已取消)',
  is_delete TINYINT(2) NOT NULL DEFAULT '2' COMMENT '是否删除标识(1-是,2-否)',
    note VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备注',
  create_user BIGINT(19) NOT NULL COMMENT '创建人id',
  create_time DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  modify_user BIGINT(19) NOT NULL COMMENT '最终修改人',
  modify_time DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '最终修改时间',
  PRIMARY KEY (id) USING BTREE
) ENGINE=InnoDB COMMENT='商品上架下架单';

DROP TABLE IF EXISTS t_ware_on_off_bill_detail;
CREATE TABLE t_ware_on_off_bill_detail (
  id BIGINT(19) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  bill_id BIGINT(19) NOT NULL COMMENT '商品上架下架单的id',
  ware_code BIGINT(19) NOT NULL COMMENT '商品编号',
  note VARCHAR(255) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (id) USING BTREE
) ENGINE=InnoDB COMMENT='商品上架下架单明细';

View Code

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

事实上,表中有更多的字段,但由于表中字段的数量不影响问题的发生,所以简化了表结构。

[En]

In fact, there are more than that in the table, but because the number of fields in the table does not affect the occurrence of the problem, the table structure is simplified.

下游系统根据 modify_time 定时进行数据的增量同步( t_ware_on_off_bill 和 t_ware_on_off_bill_detail 都会进行更新)

部分数据未同步

因此,一些数据不会同步。

[En]

As a result, some of the data are not synchronized.

让我们先重现这个问题。初值数据如下。

[En]

Let’s reproduce the problem first. The initial data are as follows.

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

此时的 modify_time 的值是 2021 -09 -08 21:18:52.602

我们来执行下更新操作

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

可以看到对 t_ware_on_off_bill 的更新结果是: 受影响的行: 0 , modify_time 并未进行更新,其值仍是 2021 -09 -08 21:18:52.602

但是 t_ware_on_off_bill_detail 是实实在在存在更新的

这就导致POS系统通过 modify_time 没有增量同步最新的商品明细

问题来了:明明对 t_ware_on_off_bill 的 N 个字段进行了 SET 操作,为什么没有记录受影响(modify_time 为什么不更新)

探究真相

相信在这个时候,很多朋友都认为房东是这样的。

[En]

I believe that at this time, many friends think that the landlord is this.

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

食物不可怕,可怕的是我们不敢面对;如果有问题,我们会找到原因并加以解决。

[En]

The food is not terrible, the fear is that we dare not face it; if there is a problem, we will find the cause and solve it.

追查原因

其实 MySQL 官方文档中有说明:11.2.6 Automatic Initialization and Updating for TIMESTAMP and DATETIME

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

这两种情况都会自动更新为系统的当前时间

[En]

Both cases are automatically updated to the current time of the system

1、insert 行时,该列没有值

2、该行的任意列的值改变了

在这一点上,我相信每个人都知道原因。

[En]

At this point, I believe everyone knows why.

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

虽然这个 SQL 很长,SET 了好几个字段,但是不满足上述两点中的任意一点,那么 modify_time 也就不会更新成系统当前时间了

解决问题

原因是我们已经找到了,如何解决问题呢?

[En]

The reason is that we have found it, how to solve the problem?

官方文档里面也说明了,显示的设值,也就是我们显示的指定 modify_time 的值,像这样

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

我们来看看实际结果

记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

当然,解决方案不止一个,你可以在评论区畅所欲言。

[En]

Of course, there is more than one solution, and you can speak freely in the comments area.

总结

1、MySQL 自动设置成系统当前时间是有条件的,否则是不会更新的哦

insert 行时,该列没有值

该行的任意列的值改变了

2、给大家留个疑问:为什么要有任意列的值改变了,MySQL 才会自动更新 modify_time 成当前系统时间,而不是只要有 SET 就更新 modify_time 成当前系统时间

Original: https://www.cnblogs.com/youzhibing/p/15186607.html
Author: 青石路
Title: 记一次线上问题 → 对 MySQL 的 ON UPDATE CURRENT_TIMESTAMP 的片面认知

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/508169/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球