起因
生产上某个筛选条件没有生效并且没有报错信息,于是到本地服务去打断点调试,为了打造相同物理条件。把涉及到的表的表结构和数据全部从生产库同步到测试库中。发现同样的查询同样的筛选条件测试上是正常的。生产上查不出来。
调试
由此定位到,应该就是这个查询SQL的问题,于是将查询的SQL单独拿出来在navicat中查询,反复在测试库和生产库中进行查询,发现同一个SQL在不同的库中同样表中的数据查询结果不同。SQL如下:
SELECT
COUNT(*) AS total
FROM
(
SELECT
`oid`,
`statistical_month`,
`order_id`,
`category`,
`goods_wh_code`,
`sort`,
`so_no`,
`document_type`,
CASE
WHEN document_type LIKE CONCAT( '拆单', '%' )
AND document_type != '拆单1' THEN
'-' ELSE item_num
END AS item_num,
`product_price`,
CASE
WHEN document_type LIKE CONCAT( '拆单', '%' )
AND document_type != '拆单1' THEN
'-' ELSE cost_price
END AS cost_price,
`receivable_amt`,
`product_id`,
`product_name`,
`sub_month`,
`ship_month`,
`finish_month`,
`subject`,
`arrival_status`,
`order_enter_amt`,
`order_enter_time`,
`order_out_amt`,
`refund_amount`,
`order_out_time`,
`last_subject`,
( CASE WHEN DATE_FORMAT( logistics_time, '%Y-%m' ) < finish_month AND finish_month = statistical_month THEN finish_month ELSE DATE_FORMAT( logistics_time, '%Y-%m' ) END ) AS logisticsTime,
`current_return_condition`,
`shop_id`,
`shop_name`,
`logistics_code`,
`logistics_name`,
`shop_order_id`,
`anchor`,
`help_anchor`,
`service_personnel`,
`remark`,
`create_by`,
`create_time`,
`update_by`,
`update_time`
FROM
fc_delivery_goods
WHERE
( sort != 'W' OR sort IS NULL )
AND oid NOT IN (
SELECT
oid
FROM
fc_delivery_goods
WHERE
( sort != 'W' OR sort IS NULL )
AND ( sub_month <= statistical_month OR sub_month IS NULL )
AND ( ship_month IS NULL OR ship_month > statistical_month )
AND (
DATE_FORMAT( order_enter_time, '%Y-%m' ) != statistical_month
OR DATE_FORMAT( order_out_time, '%Y-%m' ) != statistical_month
OR ( CASE WHEN DATE_FORMAT( logistics_time, '%Y-%m' ) < finish_month AND finish_month = statistical_month THEN finish_month ELSE DATE_FORMAT( logistics_time, '%Y-%m' ) END ) != statistical_month
OR order_out_time IS NULL
OR order_enter_time IS NULL
OR ( CASE WHEN DATE_FORMAT( logistics_time, '%Y-%m' ) < finish_month AND finish_month = statistical_month THEN finish_month ELSE DATE_FORMAT( logistics_time, '%Y-%m' ) END ) IS NULL
)) UNION ALL
SELECT
`oid`,
`statistical_month`,
`order_id`,
`category`,
`goods_wh_code`,
`sort`,
`so_no`,
`document_type`,
CASE
WHEN document_type LIKE CONCAT( '拆单', '%' )
AND document_type != '拆单1' THEN
'-' ELSE item_num
END AS item_num,
`product_price`,
CASE
WHEN document_type LIKE CONCAT( '拆单', '%' )
AND document_type != '拆单1' THEN
'-' ELSE cost_price
END AS cost_price,
`receivable_amt`,
`product_id`,
`product_name`,
`sub_month`,
`ship_month`,
`finish_month`,
`subject`,
`arrival_status`,
`order_enter_amt`,
`order_enter_time`,
`order_out_amt`,
`refund_amount`,
`order_out_time`,
`last_subject`,
( CASE WHEN DATE_FORMAT( logistics_time, '%Y-%m' ) < finish_month AND finish_month = statistical_month THEN finish_month ELSE DATE_FORMAT( logistics_time, '%Y-%m' ) END ) AS logisticsTime,
`current_return_condition`,
`shop_id`,
`shop_name`,
`logistics_code`,
`logistics_name`,
`shop_order_id`,
`anchor`,
`help_anchor`,
`service_personnel`,
`remark`,
`create_by`,
`create_time`,
`update_by`,
`update_time`
FROM
fc_delivery_goods
WHERE
sort = 'W'
AND oid NOT IN (
SELECT
oid
FROM
fc_delivery_goods
WHERE
sort = 'W'
AND ( sub_month <= statistical_month OR ship_month <= statistical_month OR sub_month IS NULL OR ship_month IS NULL )
AND finish_month IS NULL
AND (
DATE_FORMAT( order_enter_time, '%Y-%m' ) != statistical_month
OR DATE_FORMAT( order_out_time, '%Y-%m' ) != statistical_month
OR ( CASE WHEN DATE_FORMAT( logistics_time, '%Y-%m' ) < finish_month AND finish_month = statistical_month THEN finish_month ELSE DATE_FORMAT( logistics_time, '%Y-%m' ) END ) != statistical_month
OR order_out_time IS NULL
OR order_enter_time IS NULL
OR ( CASE WHEN DATE_FORMAT( logistics_time, '%Y-%m' ) < finish_month AND finish_month = statistical_month THEN finish_month ELSE DATE_FORMAT( logistics_time, '%Y-%m' ) END ) IS NULL
))) a
WHERE
a.statistical_month = '2023-08'
AND a.logistics_code IN ('CA034')
AND a.category IN ('箱包')
上述SQL是根据sort字段的不同值加以不同的条件分别查出结果,在通过union all连接到一块,最终在这个结果集中再按条件查询。对结果集查询共有三个条件,依次对三个条件进行单独查询发现,只要查询category这个条件就会出现无数据的情况。
当时第一反应就是两个库的数据库版本不一样,毕竟相同的查询SQL相同的表相同的数据查询结果不一样。那除了数据库的版本其他的也没有不同了。于是去问运维,运维说数据库版本是一样的,我天真的相信了。
于是去百度,百度到了有同学也有遇到类似的问题,但是只是记录了这个问题,并没有写出问题的原因。文章链接mysql 不同库,同表同结构同数据,查询结果不一样
他文章上的SQL也是存在子查询的情况,和我的情况类似。
又排除了其他可能导致的问题,最终还是定位在了两个库的版本不一致的问题上,于是又去找运维确认数据库的版本。
果然,测试库的数据库版本是8.0.34,生产库的数据库版本是8.0.32。差了两个小版本。查到这,基本上确定了是数据库版本不一致导致的这个问题,虽然还没有验证。
结果
中午,运维对生产数据库的版本进行了升级,升级之后问题解决。
于是去查询了MYSQL8.0.34和8.0.32两个版本的区别,查询到了这篇文章MySQL官方建议跳过8.0.28-32版本,推荐使用MySQL 8.0.34
这篇文章中大致内容如下:
- 2023年8月3日消息,MySQL副总裁Edwin Desouza近日指出MySQL 8.0.28-32 版本存在一些问题,建议用户使用8.0.33,或最好使用8.0.34。
- 根据Desouza的建议,该推荐是基于一些在8.0.28-32版本中出现的问题。虽然这些问题可能不会对所有用户产生直接影响,但在某些特定情况下可能会造成数据丢失、性能下降或不一致的查询结果。为了确保用户的数据安全和数据库的稳定性,MySQL官方建议用户直接升级到8.0.34版本。
- MySQL 8.0.34版本是经过全面测试和验证的,修复了许多在之前版本中发现的问题,并提供了更好的性能和稳定性。因此,对于正在使用8.0.28-32版本的用户,升级到8.0.34版本是一个明智的选择。
于是去查询官方解释8.0.34的修改内容
但是没有看到关于一些子查询没有查询到数据问题的解释。也并不确定是不是如我上述场景下所有类似的查询都会出现这种情况。
总之,通过升级mysql版本,我的这条SQL未查询到数据的问题解决了,希望可以帮到遇到同种场景的同学。