转载 postgres20 https://blog.csdn.net/postgres20/article/details/83415192
近日在做JWT登录时,在校验Token的创建时间与用户上次登录时间,发现总有一定概率Token判断是过期的.经过日志打印了,发现Token过期时,总是比上次登录时间少1秒(实际应该一致或者略微延迟一点毫秒值).
后续在网上找了一些原因,发现我的问题是因为Mysql在保存时间时,会针对时间类型数据中的毫秒精度进行四舍五入,大于0.5秒则加1秒,导致与我在代码中设置的时间不一致,所以存在数据库时间总是比实际时间多1秒的情况.
网上这位大神回答引用如下:
在引擎层,从row_insert_for_mysql一路往回找,最终发现在my_datetime_round 处理精度阶段,里面调用的datetime_add_nanoseconds_with_round函数,如下:
简单来说,处理逻辑就是对于时间小数部分(second_part)四舍五入,小于0.5直接return,大于0.5秒的就调date_add_interval加一秒
以上是存储层.实际在SQL层对时间处理也不一样
sql层在还原insert语句时,把参数取出拼到thd->query_string, general_log和binlog都是从这取的sql, 在set_param_datetime函数中设置参数,在这里执行param->set_time 设置时间
在进行make_truncated_value_warning 截断精度处理时,MY_MIN(decimals, DATETIME_MAX_DECIMALS) ,decimals为初始值0,所以MY_MIN(decimals, DATETIME_MAX_DECIMALS)值为0,所以这里传入make_truncated_value_warning 函数的精度值为0,精度会被直接丢弃不做任何处理.