粗大事了

几个月前使用了MySQL的5.7版本,具体版本号是mysql5.7.10,用了几个月没问题。

突然有一天,某位同事告诉,后台数据有点异常。查了一下,惊呆了,果然有问题,并且是mysql查询语句(distinct)的结果有问题导致的。最直观的表现:

SELECT
    count(DISTINCT ooo)
FROM
    xxx
WHERE
    reserve = 1047
-- 结果 81915
SELECT
    count(*)
FROM
    (
        SELECT DISTINCT
            ooo
        FROM
            xxx
        WHERE
            reserve = 1047
    ) AS t
-- 结果 65182

ooo是一个字符串类型,起先以为里面包含无法显示的特殊字符,但测试后并没有。

经过更加详细的测试,发现修改ooo字段的长度竟然也会影响到count(distinct ooo)的结果。长度越长,值越大,长度越小,值越小。wtf!!!

寻找蛛丝马迹

马上

去mysql的github的release版本历史里面去查changelog,发现了这么一条:

https://github.com/mysql/mysql-server/commit/e74e5ad5c182eee265ae6e85a82aeb08992404fa

Bug #22343910: SELECT DISTINCT NOT RETURNING DISTINCT ROWS

详细的围观了这个bug的描述,很遗憾,们的表现不属于里面的这种情况,并且里面提供的解决方案经过测试也无效。但是依然不能放弃,各种修改字段属性,依旧无效,可以放弃了,只能重新安装MySQL。。。

初步方案

接下来的问题是如何选择版本,2条路可以选择:

  • 升级版本。
  • 回退版本。

先测试5.7.13最新版,测试结果没问题。

接下来测试5.6.10GA版,测试也没问题,但坑爹的这个版本在loda data infile的时候报了一个错

Row 1 was truncated; it contained more data than there were input columns

心里一万只草泥马奔过啊,项目中用到了大量的infile和outfile,这可是官方GA版本啊!

接下来测试5.5.20,选择这个版本的原因是很多其他服务是用的这个版本。测试全部没问题,包括那个load data infile。

虽然最新版5.7.13暂时没有测出问题,但由于有了5.7.10的那个现在才出现的bug,已经对新版本的稳定性产生了严重的怀疑,5.6版本也不敢用,只能退到5.5.20了。

接下来是漫长的导数据。。。

但还是遇到了坑,通常们都是升版本,但降版本有很多问题,就是某些表结构描述或字段描述是新版本才有的,如果你用mysqldump导出后导入到低版本,恭喜你,你之前花几个小时导的数据白导了!提示:

STATS_PERSISTENT=0

语法有问题。。。

but,这难不倒机智的,用sh批量过滤掉,但又报了另外一个错。。。。

想想解决了1个后面还会有N个,并且还不知道过滤后会不会有其他问题,只能放弃了。

那么怎么办呢?

解决方案

当时想到4个可以尝试的方案:

  1. 查看mysqldump的help,看是否可以导出指定版本的数据,实现dump源是5.7,但dump出的数据是5.5可识别的语句,很遗憾,没有
  2. 使用5.5的mysqldump导出5.7的数据,看是否能导出5.5可识别的语句,很遗憾,不行
  3. mysqldump仅导出insert语句,赶紧查help,发现参数:--no-create-info --no-create-db,完美解决
  4. 如果第3个方案没找到相关参数,还有必杀技,使用load data outfile,抛弃坑爹的mysqldump!

虽然整个过程很痛苦,但终究还是解决了,最后总结还是标题那句谨慎使用mysql5.7,生产环境请珍爱生命远离5.7!

如果您觉得您在我这里学到了新姿势,博主支持转载,姿势本身就是用来相互学习的。同时,本站文章如未注明均为 hisune 原创 请尊重劳动成果 转载请注明 转自: 谨慎使用MySQL5.7 - hisune.com