在服务器标志表之间传输的表文件崩溃

时间:2014-05-22 14:25:04

标签: mysql ruby net-ssh net-sftp

Work有一个使用大型数据集的网站,使用MyISAM在两个MySQL 5.6.16-64.2服务器之间进行负载平衡,在Linux上运行(2.6.32-358.el6.x86_64 GNU / Linux。)这个数据正在每小时从从MS-SQL数据库接收的基于文本的文件集更新。为了避免对网站上的读取造成干扰,同时确保更新不会花费太长时间,因为过程已经到位:

将数据放在第三个Linux框(仅用于数据更新处理),根据需要更新不同的数据表,将物理表文件的副本移动到临时名称下的生产服务器,然后执行表通过MySQL TABLE RENAME交换。

但每次表(在临时名称下)被目标MySQL服务器看作崩溃并需要修复。修复需要的时间太长,因此在进行表交换之前不能强制进行修复。

通过为每个服务器提供一个线程,在Ruby 1.8.7中编写处理程序(就像一个FYI,如果不在一个线程中执行它,也会发生这种情况。)

执行文件复制的步骤如下:

使用Net :: SFTP将文件传输到不是数据库文件夹的目标文件夹(由于权限而完成。)主表文件的文件传输的代码示例(如果表也有分区文件,那么它们是单独传输并且rspFile的分配方式与临时名称不同。)对于速度,它是并行上传的:

Net::SFTP.start(host_server, host_user, :password => host_pwd) do |sftp|
  uploads = fileList.map { |f|
    rcpFile = File.basename(f, File.extname(f)) + prcExt + File.extname(f)
    sftp.upload(f, "/home/#{host_user}/#{rcpFile}")
  }
  uploads.each { |u| u.wait }
end

然后将所有者和组的文件分配给mysql用户并将文件移动到MySQL数据库文件夹,使用Net :: SSH执行sudo shell命令:

Net::SSH.start(host_server, host_user, :port => host_port.to_i, :password => host_pwd) do |ssh|
  doSSHCommand(ssh, "sudo sh -c 'chown mysql /home/#{host_user}/#{prcLocalFiles}'", host_pwd)
  doSSHCommand(ssh, "sudo sh -c 'chgrp mysql /home/#{host_user}/#{prcLocalFiles}'", host_pwd)
  doSSHCommand(ssh, "sudo sh -c 'mv /home/#{host_user}/#{prcLocalFiles} #{host_path}'", host_pwd)
end

doSSHCommand方法:

def doSSHCommand(ssh, cmd, pwd)
  result = ""
  ssh.open_channel do |channel|
    channel.request_pty do |c, success|
        raise "could not request pty" unless success

      channel.exec "#{cmd}" do |c, success|
          raise "could not execute command '#{cmd}'" unless success

        channel.on_data do |c, data|
          if (data[/\[sudo\]|Password/i]) then
            channel.send_data "#{pwd}\n"
          else
            result += data unless data.nil?
          end
        end
      end
    end
  end
  ssh.loop

  result
end

如果使用scp手动完成移动文件,请执行所有者/组更改,然后移动文件,然后永远不会崩溃表。通过检查scp和Net :: SFTP之间的文件大小,没有区别。

已经尝试过其他处理方法,但与使用上述方法相比,经验花费的时间太长。任何人都知道为什么桌面崩溃,以及是否有解决方案以避免表崩溃而不必进行表修复?

3 个答案:

答案 0 :(得分:0)

这些表被标记为崩溃,因为您在复制文件时可能会遇到竞争条件。也就是说,在执行Ruby脚本期间,有些表会挂起表,因此生成的副本不完整。

复制MyISAM表的更安全的方法是首先运行SQL命令FLUSH TABLES,然后运行FLUSH TABLES WITH READ LOCK,以确保将所有挂起的更改写入磁盘上的表,然后阻止任何进一步的更改直到你释放表锁。然后执行复制脚本,最后解锁表。

这意味着没有人可以在复制时更新表格。这是确保您获得未损坏文件的唯一方法。

但我必须评论一下,你似乎正在重塑MySQL replication。你有没有理由不使用它?它可以更快,更好,更有效地工作,逐步地,不断地更新已更改的表的部分。

答案 1 :(得分:0)

问题被找到并解决了:

流程数据库具有从其中一个生产数据库复制的表文件,并且未在流程服务器上显示崩溃,并且在查询和更新数据时没有问题。

在搜索网页后,我们找到了答案:MySQL table is marked as crashed

因此,通过猜测当表从生产复制到流程服务器时,标题信息保持不变,并且在处理器期间复制回生产服务器时可能会产生干扰。因此,尝试修复流程服务器上的表,然后在我们的临时环境中运行一些测试,同时也遇到问题。肯定足以纠正这个问题。

所以最终的解决方案是在进程脚本每小时运行一次之前在进程服务器上修复一次表。

答案 2 :(得分:0)

我看到你已经找到了答案,但有两件事让我对这个问题感到震惊。

其中一个,你应该看看rsync,这会给你更多的选择,其中最重要的是更快速的转移,可能更适合这个问题。服务器之间的文件传输基本上是rsync存在的原因。

其次,我并没有尝试重新设计你的系统,但你可能已经超越了MySQL。它可能不是最适合这个问题的。 Riak可以更好地为您提供多个节点,或Mongo,您可以处理大型文件并拥有多个节点。在阅读你的问题时我只有两个想法。