查询条件使用now()函数,相同sql代码执行结果与数据库执行结果不一致

【 TiDB 使用环境】生产环境 、测试环境
【 TiDB 版本】v6.5.3
【复现路径】
【遇到的问题:问题现象及影响】
springboot项目使用mybatis生成sql并执行,where条件中使用到了now()函数计算日期间隔,代码执行结果通过日志查询,共查询出1000+条数据,但是实际上抓取这条sql在tidb直接执行,查询结果有5000+条数据,两者的执行结果不一致导致执行的逻辑有误差。
使用日志打印过代码中执行出的now()的时间,与数据库直接执行select now()对比,两者时间是相同的,并且根据附件4的结果可以基本排除是时区差异导致的问题。
注:直接在本地运行则不存在误差,都能查出5000+条
【附件:截图/日志/监控】


image
image
附件4:

完整的大致SQL为:
select *
from table_a
where
(doc_status = ‘20’ or (doc_status = ‘11’ and TIMESTAMPDIFF(DAY, creation_date, now()) < ‘100’))
and TIMESTAMPDIFF(DAY, creation_date, now()) < ‘300’;
尝试过将now()函数替换为current_timestamp()函数,结果也是一样。
最后处理方案是不在SQL中使用now()函数,而是将日期当作入参直接传入,这样代码也能够执行出正确的结果,修改后的SQL如下:
select *
from table_a
where
(doc_status = ‘20’ or (doc_status = ‘11’ and TIMESTAMPDIFF(DAY, creation_date, 入参进来的准确日期’2024-01-25’) < ‘100’))
and TIMESTAMPDIFF(DAY, creation_date, ‘入参进来的准确日期’2024-01-25‘’) < ‘300’;

"本地"是指mysql客户端吗?在两个环境中分别打印now()的值是否相差过大。

now() 取的是执行对应sql的时候的当前时间,不同的环境执行出来不同的结果是预期现象呀。因为你执行的时间不同。 取到的now() 的结果就是不同的。
可以分别执行下看看now() 的结果,也可能是时区之类的问题导致这个差值超过本身执行的时间差距。

本地指的是在自己电脑上运行程序;数据差异并不是说生产环境和测试环境有差异,是生产环境的代码执行结果和生产环境直接执行sql的结果相比有差异,并且这个问题在测试环境也能够复现。
代码执行出的now()结果和数据库直接select now()的结果是一样的,这个做过验证,基本可以排除是时区问题。

1、数据差异并不是说生产环境和测试环境有差异,是生产环境的代码执行结果和生产环境直接执行sql的结果相比有差异,并且这个问题在测试环境也能够复现。缺失的那部分数据的时间实际上是几个月前的数据,时间远远超过代码执行-拿出sql在数据库执行的时间(这个时间最多只间隔一分钟)
2、代码执行出的now()结果和数据库直接select now()的结果是一样的,这个做过验证,也能排除是时区问题。

"代码执行出的now()结果"中的now()是java的函数吗?
无论具体环境是什么,在产生差异的系统中执行sql的now()函数看看是否有差异。

极有可能是因为时区UTC不一样,或者另外的条件导致的,可以从数据结果的时间戳比较一下

使用日志打印过代码中执行出的now()的时间,与数据库直接执行select now()对比,两者时间是相同的,并且根据附件4的结果可以基本排除是时区差异导致的问题。

奥,那没啥别的思路了

1、“代码执行出的now()结果”指的也是sql的now()函数,只是通过代码执行sql并打印出这个结果。
2、都执行过,除去执行时间的差异,得出的时间是一致的。

去dashboard上把两条SQL的文本与执行计划拿出来看下

如果把now()赋值到变量里,sql语句用变量查询,结果会有差异吗?

now()就是SQL的函数,怎么将它赋值到变量中呢额 :face_with_monocle:

试一下 set @var=‘select now()’

完全相同–

这个或许有可能吧。

actrows也一样吗?

应用是不是从未重启过?由于事务方面MVCC的原因读取的是之前版本的数据?

请贴从dashboard上看到的SQL文本和执行计划,不然没法帮你分析