MacOS 系统上的 MySQL Docker Container INFILE/INTO OUTFILE 语句

2022-09-01 14:48:24

我有一个Java程序和一个mysql Docker容器(图片:mysql:5.7.20)。我的 MacOs 是 High Sierra 10.13.4。

简而言之,问题

在 MacOS 上使用 Docker (10.13.4.)。在 docker 容器(图片:mysql:5.7.20)中,主要是查询(从 java 程序执行)

  • LOAD DATA INFILE ...
  • SELECT ... INTO OUTFILE ...

工作正常,但有时 java 程序会引发异常:

  • SQLException:无法创建/写入文件“...”。(错误代码:2 - 没有此类文件或目录)
  • SQLException:无法获取“...”的统计信息错误代码: 2 - 没有这样的文件或目录)
  • SQLException:MySQL服务器使用--secure-file-priv选项运行,因此它无法执行此语句
  • SQLException: File '...'未找到(错误代码:2 - 无此类文件或目录)

顺便说一句。文件存在并且权限应该没问题(请参阅更长的版本)

加长版

该过程如下:

  • 创建.csv文件
  • 此.csv文件被复制到一个目录中,该目录是为 docker 容器挂载的
    • docker-compose volumes 部分:- "./data/datahub/import:/var/lib/mysql-files/datahub/import"
  • 然后MySQL将此.csv文件读入表中:
    • LOAD DATA INFILE '.csv-file' REPLACE INTO TABLE 'my-table';
  • 然后该数据库上的一些东西发生了
  • 之后,MySQL写入.csv输出文件
    • SELECTtblskutbldeletedtbldata_source_values.,.,.INTO OUTFILE 'output.csv' FIELDS TERMINATED BY '|' ENCLOSED BY '"' ESCAPED BY '"' FROM (SELECT ...

这个项目有一些Java集成测试用于这个过程。这些测试大多是绿色的,但有时它们会失败:

  • SQLException:无法创建/写入文件“...”。(错误代码:2 - 没有此类文件或目录)
  • SQLException:无法获取“...”的统计信息错误代码: 2 - 没有这样的文件或目录)
  • SQLException:MySQL服务器使用--secure-file-priv选项运行,因此它无法执行此语句
  • SQLException: File '...'未找到(错误代码:2 - 无此类文件或目录)

docker-compose 文件如下所示:

version: '3'
  services:
    datahub_db:
      image: "mysql:5.7.20"
      restart: always
      environment:
        - MYSQL_ROOT_PASSWORD=${DATAHUB_DB_ROOT_PASSWORD}
        - MYSQL_DATABASE=${DATAHUB_DB_DATABASE}
      volumes:
        - "datahub_db:/var/lib/mysql"
        - "./data/datahub/import:/var/lib/mysql-files/datahub/import"
        - "./data/akeneo/import:/var/lib/mysql-files/akeneo/import"
      ports:
        - "${DATAHUB_DB_PORT}:3306"

...

volumes:
  datahub_db:

来自该 Docker 数据库容器的日志显示以下内容(但有时,当所有测试也为绿色时,也会发生这种情况)

  • datahub_db_1 | 2018-06-01T10:04:33.937646Z 144 [Note] Aborted connection 144 to db: 'datahub_test' user: 'root' host: '172.18.0.1' (Got an error reading communication packets)

数据集线器容器内的.csv文件如下所示:ls -lha

root@e02e2074fb6b:/var/lib/mysql- 
files/datahub/import/test/products/kaw# ls -lha
total 4.0K
drwxr-xr-x 3 root root  96 Jun  1 09:36 .
drwxr-xr-x 3 root root  96 Jun  1 09:36 ..
-rw-r--r-- 1 root root 378 Jun  1 06:47 deactivated_product_merged_bub.csv

我认为没有问题,这个文件属于root,因为大多数这个文件可以被MySQL读取。当我通过 Docker 容器内部更改为用户时,我得到以下内容:mysqlsu mysql

$ ls -al
total 4
drwxr-xr-x 3 mysql mysql  96 Jun  1 09:36 .
drwxr-xr-x 3 mysql mysql  96 Jun  1 09:36 ..
-rw-r--r-- 1 mysql mysql 378 Jun  1 06:47 deactivated_product_merged_bub.csv

现在发生了一些奇怪的事情。

  • 与根用户,我可以做一个cat deactivated_product_merged_bub.csv
  • 与mysql用户我不能得到:

输出:

$ cat deactivated_product_merge_bub.csv
cat: deactivated_product_merge_bub.csv: No such file or directory

我做了一个MySQL用户,突然间我可以在该文件上做一个(正如你所看到的,我到那个文件来获得工作 - 但它不起作用)。stat deactivated_product_merged_bub.csvcatchmod 777cat

  • stat作为根

输出:

root@e02e2074fb6b:/var/lib/mysql-files/datahub/import/test/products/kaw# stat 
deactivated_product_merged_bub.csv 
  File: 'deactivated_product_merged_bub.csv'
  Size: 378         Blocks: 8          IO Block: 4194304 regular file
Device: 4fh/79d Inode: 4112125     Links: 1
Access: (0777/-rwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2018-06-01 09:23:38.000000000 +0000
Modify: 2018-06-01 06:47:44.000000000 +0000
Change: 2018-06-01 09:04:53.000000000 +0000
  Birth: -
  • stat作为 mysql 用户

输出:

$ stat deactivated_product_merged_bub.csv
  File: 'deactivated_product_merged_bub.csv'
  Size: 378         Blocks: 8          IO Block: 4194304 regular file
Device: 4fh/79d Inode: 4112125     Links: 1
Access: (0777/-rwxrwxrwx)  Uid: (  999/   mysql)   Gid: (  999/   mysql)
Access: 2018-06-01 09:32:25.000000000 +0000
Modify: 2018-06-01 06:47:44.000000000 +0000
Change: 2018-06-01 09:04:53.000000000 +0000
  Birth: -

问题

有谁知道,这里发生了什么,或者有提示我可以搜索到更深入的挖掘?

我的推测是,这是因为将Docker与MacO和挂载的卷一起使用。


答案 1

在我看来,您可能会在这里遇到两个单独的问题,这两个问题都与MySQL服务器的配置有关。

MySQL服务器使用--secure-file-priv选项运行,因此它无法执行此语句。

此选项要求将任何文件加载或文件导出放置在文件系统中的指定存储位置。您可以使用以下命令从MySQL命令行客户端或MySQL Workbench中找到该位置:

mysql> show variables like 'secure-file-priv';

由此产生的结果应确定可以加载和写出文件的位置。启用安全文件私有时,不应允许其他位置。

(读取通信数据包时出错)

这通常是由于加载或导出的数据超过了MySQL变量max允许的数据包。

同样,您可以使用以下命令从 MySQL 命令行客户端或 MySQL 工作台中找到最大允许数据包的值:

mysql> show variables like 'max-allowed-packet';

这个问题已经得到解决并得到了很好的回答:https://dba.stackexchange.com/questions/19135/mysql-error-reading-communication-packets

总而言之:在 /etc/my.cnf 或 my.ini [mysqld] 部分下:

[mysqld]
max_allowed_packet=268435456

‬In the running MySQL instance:

SET GLOBAL max_allowed_packet = 268435456;

(无需重新启动服务。

顺便说一句,您使用的MySQL帐户必须已被授予“FILE”权限才能加载或导出。由于您使用的是MySQL根(管理)帐户,因此这不应该是一个因素,但我认为我会为遇到此问题的任何人提供它。

我希望这有帮助。


答案 2

您可能正在尝试访问位于 mac 泊坞窗的默认共享路径之外的文件(来自 docker osx 文档)

默认情况下,您可以直接在 /Users/、/Volumes/、/private/ 和 /tmp 中共享文件。要添加或删除导出到 Docker 的目录树,请使用 Docker 首选项 whale 菜单 ->首选项 ->文件共享中的文件共享选项卡。(请参阅首选项。

https://docs.docker.com/docker-for-mac/osxfs/#namespaces

在这种情况下,mac的docker正在使用由Mac OS上的hyperkit运行的Linux虚拟机。客户端在 macOSx 和 VM 中的守护程序上运行。这说明您必须在受限制的路径列表中共享文件。


推荐