【问题标题】:Different result in mysql in windows and linuxwindows和linux中mysql的结果不同
【发布时间】:2016-11-29 17:23:11
【问题描述】:

我正在将 mysql 从 linux 迁移到 Windows 机器。我有一个更新查询,它使用映射表在 windows 和 linux 中给出不同的结果。 我提供了重新创建问题的步骤以及我得到的结果。

在 Linux 中按照以下步骤操作:

  1. 创建所需的表

    CREATE TABLE `buildmapping` ( 
    `ver` varchar(36) DEFAULT NULL, 
    `build` varchar(36) DEFAULT NULL, 
    `branchname` varchar(36) DEFAULT NULL, 
    `buildminor` varchar(36) DEFAULT NULL, 
    UNIQUE KEY `bmap` (`ver`,`build`,`branchname`,`buildminor`), 
    KEY `ak` (`ver`), 
    KEY `br` (`branchname`), 
    KEY `bi` (`build`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; 
    
    CREATE TABLE `s_Last7days` ( 
    `ver` varchar(36) DEFAULT NULL, 
    `build` varchar(36) DEFAULT NULL, 
    `branchname` varchar(36) DEFAULT NULL, 
    `buildminor` varchar(36) DEFAULT NULL 
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1; 
    
  2. 插入所需数据

    Insert into buildmapping values ('1522','105','release_01','682');
    Insert into buildmapping values ('1384','105','release_01','682');    
    Insert into buildmapping values ('1090','105','release_01','682');
    Insert into s_Last7days values ('0','105','release_01','682');
    
  3. 使用映射表更新事实

    update s_Last7days b , buildmapping c 
    set b.ver=c.ver 
    where b.ver=0 
    and b.Build=c.build 
    and b.BuildMinor=c.buildminor 
    and b.branchname=c.branchname; 
    
  4. 验证数据

    select * from s_Last7days; 
    
    +------+-------+------------+------------+
    | ver  | build | branchname | buildminor |
    +------+-------+------------+------------+
    | 1522 | 105   | release_01 | 682        |
    +------+-------+------------+------------+ 
    
  5. 从 Linux 服务器获取转储:

    mysqldump -uxxxxx -pxxxxxx -hxxxxx databasename buildmapping > buildmapping_bk1128.sql 
    
  6. SSH 文件到 Windows 服务器

在 Windows 服务器中执行以下步骤:

  1. 在 Windows 中恢复表。 (我用的是 MySQL Workbench)

  2. 创建所需的表

    CREATE TABLE `s_Last7days` ( 
    `ver` varchar(36) DEFAULT NULL, 
    `build` varchar(36) DEFAULT NULL, 
    `branchname` varchar(36) DEFAULT NULL, 
    `buildminor` varchar(36) DEFAULT NULL 
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1; 
    
  3. 插入所需数据

    Insert into s_Last7days values ('0','105','release_01','682'); 
    
  4. 使用映射表更新事实

    update s_Last7days b , buildmapping c 
    set b.ver=c.ver 
    where b.ver=0 
    and b.Build=c.build 
    and b.BuildMinor=c.buildminor 
    and b.branchname=c.branchname; 
    
  5. 验证数据

    select * from s_Last7days; 
    
    +------+-------+------------+------------+
    | ver  | build | branchname | buildminor |
    +------+-------+------------+------------+
    | 1090 | 105   | release_01 |  682       |
    +------+-------+------------+------------+ 
    

我希望两台服务器同步。有人可以帮我解决这个问题吗?

【问题讨论】:

  • 您的buildmapping 表有多个与branchnamebuildminor 匹配的行。看起来 Windows 和 Linux 正在以不同的顺序获取它们。
  • 如果是这种情况(我快速扫描)这意味着你搞砸了你的逻辑
  • 问题是您假设每次都会以相同的顺序返回行,但事实并非如此。确保行排序的唯一方法是包含 ORDER BY。
  • 是的,多条记录满足条件。它在映射表中的错误。但是这个系统是很久以前开发的,即使映射表中有重复项,当前的 linux 系统也可以按预期工作。它不是我开发的,我只是在做迁移工作。任何线索如何使 windows 服务器选择与 linux 相同的记录?
  • 我们刚刚告诉过你。添加 ORDER BY 以选择 TOP 1 ORDER BY ver DESC。假设任何事情都不安全,尤其是在处理数据时。

标签: mysql sql-order-by


【解决方案1】:

SQL 的一个特点是,在没有ORDER BY 子句的情况下指定的结果集以不可预测 的顺序返回其行。这有点像说它们是按随机顺序返回的。但是,问题是,它们通常以与上次相同的顺序返回,直到它们不是。如果这些东西真的是随机的,那么你在 Linux 上的数据库中就会出现这样的缺陷不太可能潜入:有人会检测到它们并修复它们。

您在这种情况下所说的结果集是。

select c.ver 
  from s_Last7days b , buildmapping c 
 where b.ver=0 
   and b.Build=c.build 
   and b.BuildMinor=c.buildminor 
   and b.branchname=c.branchname; 

请注意,它返回三个不同的 ver 值。当您在更新中使用此结果集时,它会更新该行 3 次,针对结果集中的每个值更新一次。碰巧最后来的就是坚持下来的那个。

您发现您在 Windows 上运行的 MySQL 服务器与您在 Linux 上运行的服务器具有不同的不可预测含义。

没有办法强制你的两台服务器具有相同的unpredictable含义。这是不可能的。您必须从查询中消除不可预测性,或者忍受不可预测性。此查询获取ver 的最大值。

select c.ver 
  from s_Last7days b , buildmapping c 
 where b.ver=0 
   and b.Build=c.build 
   and b.BuildMinor=c.buildminor 
   and b.branchname=c.branchname
 order by c.ver DESC
 limit 1

您的 Linux 数据库存在一个错误,导致无法原封不动地移植到 Windows。您很幸运(或者可能是不幸),直到现在该错误仍未被发现。您必须在移植此数据库时修复此错误,否则将承担错误的后果。

【讨论】:

  • 谢谢琼斯、火箭、德鲁和肯。是的,我会尝试在当前服务器中修复它。这将是最佳解决方案。
【解决方案2】:

您的更新命令正在使用一对多关系来选择应该将构建映射中的哪个值用于 s_Last7days.ver 字段。 所以只会使用自然顺序中第一个匹配的元组。

更多信息here

【讨论】:

    猜你喜欢
    • 2018-01-10
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 2020-08-01
    • 2021-07-16
    • 2015-05-04
    相关资源
    最近更新 更多