MYSQL同表同数据同结构同SQ L在两个服务器上数据库里查到的结果不一样

作者在生产环境中遇到SQL查询结果在测试库正常但在生产库异常的问题,经排查发现是由于MySQL数据库版本(8.0.32vs8.0.34)不一致导致。升级生产库到8.0.34后问题解决,强调了版本更新的重要性。
摘要由CSDN通过智能技术生成

MYSQL同表同数据同结构同SQ L在两个服务器上数据库里查到的结果不一样

起因

生产上某个筛选条件没有生效并且没有报错信息,于是到本地服务去打断点调试,为了打造相同物理条件。把涉及到的表的表结构和数据全部从生产库同步到测试库中。发现同样的查询同样的筛选条件测试上是正常的。生产上查不出来。

调试

由此定位到,应该就是这个查询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

这篇文章中大致内容如下:

  1. 2023年8月3日消息,MySQL副总裁Edwin Desouza近日指出MySQL 8.0.28-32 版本存在一些问题,建议用户使用8.0.33,或最好使用8.0.34。
  2. 根据Desouza的建议,该推荐是基于一些在8.0.28-32版本中出现的问题。虽然这些问题可能不会对所有用户产生直接影响,但在某些特定情况下可能会造成数据丢失、性能下降或不一致的查询结果。为了确保用户的数据安全和数据库的稳定性,MySQL官方建议用户直接升级到8.0.34版本。
  3. MySQL 8.0.34版本是经过全面测试和验证的,修复了许多在之前版本中发现的问题,并提供了更好的性能和稳定性。因此,对于正在使用8.0.28-32版本的用户,升级到8.0.34版本是一个明智的选择。

于是去查询官方解释8.0.34的修改内容

官方解释8.0.34的修改内容

但是没有看到关于一些子查询没有查询到数据问题的解释。也并不确定是不是如我上述场景下所有类似的查询都会出现这种情况。

总之,通过升级mysql版本,我的这条SQL未查询到数据的问题解决了,希望可以帮到遇到同种场景的同学。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值