数据日志的重要性 | MySQL timestamp on update
前言
两周前接了个活儿,甲方的公众号需要做一个前端记录用户信息,管理端查看用户填写的信息并且审批的项目。
甲方提供短信平台接口,公众号获取openid的转接接口,FTP服务器,数据库。
项目制作也没有多难,本地测通以后,把项目放到我自己的服务器里模拟了一下,都通了才放到甲方的FTP里。
原本投产时间是周一,但是周四甲方临时要求放到周五投产,这样他们周末出去推广的人就能用了。
因为我已经做完了,和甲方的技术联调也都完成了,于是周五下午给他上掉。
发现问题
周末出差,周日晚上才到家。
看了一下数据库,发现问题,信息表的创建时间都是0时几分几秒,而手机绑定时间都是8时同分同秒。
甲方给的数据库默认时间是UTC,但是代码里只有创建数据的时候才会给创建时间设值。SHOW VARIABLES LIKE '%time_zone%';
Variable name | Value |
---|---|
system_time_zone | Coordinated Universal Time |
time_zone | SYSTEM |
仔细撸了一遍代码并没有发现问题,将生产环境的代码和本地对比了一下也无差异。接着在本地和自己的服务器里(修改了mysql的配置文件,将时区也设为UTC)又赶紧测了一次也没有出现问题。
正感觉一筹莫展的时候,用sqlyog
的Schema Synchronization Tool
对比了一下生产与本地的数据库发现问题了。
此时生产环境数据库内的表结构是类似这样的。
在本地模拟了一下,确定了是on update的问题,赶紧先把生产环境的on update去掉,之后的数据创建时间都正常了。
数据修复
接着找办法修复那些错误的创建时间。
好在有之前做项目中学到的防止扯皮好习惯,在建表的时候多建了一张some_data_log
表,用来记录数据的增删改操作。其中就有进行操作的时间,可以用对表名为some_info_table
的表进行insert操作时的操作时间来作为some_info_table
中数据的创建时间。
虽然data_log
和info_table
并没有什么字段可以关联,也就是说普通的update join并不可行。但是错误的创建时间数据条数是能够在data_log
表中找到对应数据的。
于是搞了一张中间表,将info_table
的涉及id按顺序插入列1,将data_log
的create_time按时间排序插入列2。
使用中间表和info_table
进行update join操作成功将数据修复了。
关于on update
按照mysql的官方手册里的说明,on update是数据类型为timestamp的一个可开启功能,在insert或update操作时都更新这个数据列的值(这个功能是给update_time用的,但是前提是配置好mysql的时区)。
For any TIMESTAMP or DATETIME column in a table, you can assign the current timestamp as the default value, the auto-update value, or both:
- An auto-initialized column is set to the current timestamp for inserted rows that specify no value for the column.
- An auto-updated column is automatically updated to the current timestamp when the value of any other column in the row is changed from its current value. An auto-updated column remains unchanged if all other columns are set to their current values. To prevent an auto-updated column from updating when other columns change, explicitly set it to its current value. To update an auto-updated column even when other columns do not change, explicitly set it to the value it should have (for example, set it to CURRENT_TIMESTAMP).
总结
这次项目虽然没有什么难度,但是最终还是掉到自己挖的沟里,好在周末甲方没有审核员上班,除了我以外并没有人知道数据出过问题(现在你也知道了)。
这次的事故出错的核心问题在于数据库图形软件用得太顺手了,以至于在加comments的时候点到了On Update,而在投产时并没有一个一个表的点开看结构,而是直接更新到生产环境服务器里。
Reference
11.3.5 Automatic Initialization and Updating for TIMESTAMP and DATETIME - MySQL v5.6