【问题标题】:Bulk insert of MySQL related tables from bash从 bash 批量插入 MySQL 相关表
【发布时间】:2012-06-25 05:08:08
【问题描述】:

我需要定期将大量数据从 CSV 文件上传到 MySQL 数据库。我通过简单地从 bash 脚本执行 LOAD DATA INFILE 来做到这一点。然而,现在数据将分布在多个表中,并且要保留关系。这种情况下的一般策略是什么?

让我们假设一个最初的简单任务:关系一对多,两个表。

我认为是这样的:

  1. 获取表 1 的最大标识符
  2. 手动将标识符应用到 CSV 文件
  3. 根据两个目标表拆分文件
  4. 插入两个表

这是最佳解决方案吗? (例如,在实际情况中,我将通过这种方式更新许多多对多关系。)

我可以在整个过程中从 bash 级别锁定表 1 吗?还是我必须使用 perl 或 Python 之类的中介工具来将所有内容保存在一个会话中?

【问题讨论】:

  • 优秀的第一篇文章!您的答案取决于您是 Immon(ite) 还是 Kimball(ite),Kimball 的数据仓库工具包 (book) (amazon.com/The-Data-Warehouse-Toolkit-Dimensional/dp/0471200247/…) 主张让系统生成人工密钥。或者尝试一种对我来说效果很好的替代方法。保留一组单独的“输入”表,将当前文件导入空输入表,然后运行存储过程以合并到主表中。祝你好运。
  • 使用 awk 对数据进行预处理/拆分,在拆分文件上只需 load data。如果您想了解更多详细信息,您必须自己提供一些。

标签: mysql bash


【解决方案1】:

您的问题中表达了各种相互矛盾的要求。这个答案集中在它的“保持锁定”方面。

为了维护整个操作的表锁,您必须维护到 sql server 的单个连接。一种方法是将所有内容作为多行多命令输入传递给 mysql 命令行客户端的单个调用。基本上是这样的:

{ echo "LOCK TABLES Table1 WRITE"
  for i in "${infiles[@]}"; do
    echo "LOAD DATA LOCAL INFILE '${i}'"
  done
} | mysql

只要您可以生成所有必需的语句,而无需在保留锁的情况下从数据库询问问题(如最大标识符),这将起作用。

为了混合读取操作(例如请求最大值)和写入操作(例如加载某些文件的内容),您需要与服务器进行双向通信。通过 bash 实现这一点非常棘手,所以我建议不要这样做。即使您不需要提问,bash 管道提供的单向连接也是一个危险源:如果 mysql 端出现任何问题,bash 不会注意到并会发出下一个命令。您最终可能会提交不一致的数据。

出于这些原因,我宁愿建议一些可以使用 mysql 绑定的脚本语言,例如您提到的 Perl 或 Pyhon 选项。阅读这些语言的 CVS 文件很容易,因此您可以在一个脚本中完成以下所有操作:

  1. 锁定表
  2. 开始交易
  3. 读取输入的 csv 文件
  4. 问最大id之类的问题
  5. 调整输入数据以匹配表格布局
  6. 将数据插入表中
  7. 如果没有发生错误,则提交事务

【讨论】:

    猜你喜欢
    • 2020-11-06
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多