mysql docker容器infile/into-outfile语句

p1iqtdky  于 2021-06-20  发布在  Mysql
关注(0)|答案(3)|浏览(409)

我有一个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:无法获取“…”的stat错误代码:2-没有这样的文件或目录)
sqlexception:mysql服务器正在使用--secure file priv选项运行,因此无法执行此语句
sqlexception:找不到文件“…”(错误代码:2-没有此类文件或目录)
顺便说一句,该文件存在,权限应该很好(请参阅较长的版本)
较长的版本
过程如下:
将创建一个.csv文件
这个.csv文件被复制到一个目录中,这个目录是为docker容器挂载的
docker撰写卷部分: - "./data/datahub/import:/var/lib/mysql-files/datahub/import" 然后mysql将这个.csv文件读入一个表: LOAD DATA INFILE '.csv-file' REPLACE INTO TABLE 'my-table'; 然后数据库里发生了一些事情
之后,mysql编写一个.csv输出文件 SELECT 待定 . 库存单位 , 待定 . 删除 , 待定 . 数据源值 INTO OUTFILE 'output.csv' FIELDS TERMINATED BY '|' ENCLOSED BY '"' ESCAPED BY '"' FROM (SELECT ... 这个项目对这个过程进行了一些java集成测试。这些测试大多是绿色的,但有时会失败:
sqlexception:无法创建/写入文件“…”(错误代码:2-没有此类文件或目录)
sqlexception:无法获取“…”的stat错误代码:2-没有这样的文件或目录)
sqlexception:mysql服务器正在使用--secure file priv选项运行,因此无法执行此语句
sqlexception:找不到文件“…”(错误代码: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) datahub容器中的.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可以读取这个文件。当我换成用户时 `mysql` 通过 `su mysql` 在docker容器中,我得到以下信息:

$ 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

现在发生了一些奇怪的事情。
使用root用户,我可以 `cat deactivated_product_merged_bub.csv` 使用mysql用户,我无法获得:
输出:

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

我做了一个 `stat deactivated_product_merged_bub.csv` 作为mysql用户,突然间我可以 `cat` 在那个文件上(如你所见,我 `chmod 777` 到那个文件去拿 `cat` 工作-但没有工作)。 `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: -

问题
有没有人知道,这里发生了什么事,或者有什么线索可以让我深入挖掘?
我的猜测是,这是因为使用macos和装载卷的docker。

jaxagkaj

jaxagkaj1#

我认为您在docker容器和主机之间共享文件夹的权限方面有问题。您需要通过在.env文件中设置uid来将容器的用户Map到主机的用户。

UID=501 # run echo $UID to get current user id
version: '3'
  services:
    datahub_db:
      image: "mysql:5.7.20"
      user: $UID
      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:
jdzmm42g

jdzmm42g2#

在我看来,您可能会遇到两个不同的问题,都与mysql服务器的配置有关。
mysql服务器使用--secure file priv选项运行,因此无法执行此语句。
此选项要求将任何文件加载或文件导出放置在文件系统中指定的存储位置。您可以使用以下命令从mysql命令行客户端或mysql工作台查找位置:

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

这样做的结果应该标识文件可以加载和写出到的位置。启用secure file priv时,不允许使用其他位置。
(读取通信数据包时出错)
这通常是由于加载或导出的数据超过mysql变量max allowed packet而导致的。
类似地,您可以使用以下命令从mysql命令行客户端或mysql工作台找到max allowed packet的值:

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

这一点在这个问题上得到了很好的解决和回答:https://dba.stackexchange.com/questions/19135/mysql-error-reading-communication-packets
总之:在[mysqld]部分下的/etc/my.cnf或my.ini中:

[mysqld]
max_allowed_packet=268435456

‬在正在运行的mysql示例中:

SET GLOBAL max_allowed_packet = 268435456;

(不需要重新启动服务。)
另外,您使用的mysql帐户必须被授予“file”权限才能加载或导出。因为您使用的是mysql root(管理)帐户,所以这不应该是一个因素,但是我想我会为任何遇到这个问题的人提供它。
我希望这有帮助。

v7pvogib

v7pvogib3#

可能是您试图访问的文件超出了docker for mac的默认共享路径(来自docker osx文档)
默认情况下,可以直接在/users/、/volumes/、/private/和/tmp中共享文件。要添加或删除导出到docker的目录树,请使用docker首选项菜单->首选项->文件共享中的文件共享选项卡(请参见首选项。)
https://docs.docker.com/docker-for-mac/osxfs/#namespaces
在这种情况下,docker for mac使用的是由hyperkit在mac os上运行的linux虚拟机。客户端在macosx上运行,守护进程在vm中运行。这就解释了你必须在一个受限的路径列表中共享文件。

相关问题