Контент MySQL Docker Container INFILE/INTO OUTFILE в системе MacOS - программирование
Подтвердить что ты не робот

Контент MySQL Docker Container INFILE/INTO OUTFILE в системе MacOS

У меня есть Java-программа и контейнер MySQL Docker (изображение: MySQL: 5.7.20). Мои MacOs - High Sierra 10.13.4.

Проблема вкратце

Использование Docker в MacOS (10.13.4.). Внутри Docker-контейнера (image: mysql: 5.7.20) в основном запросы (выполняемые из Java-программы)

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

работают нормально, но иногда Java-программа выдает исключения:

  • SQLException: Невозможно создать/записать в файл '… (код ошибки: 2 - такого файла или каталога нет)
  • SQLException: Невозможно получить статистику '… Errcode: 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 ТАБЛ . sku , tbl . удалено , табл . data_source_values INTO OUTFILE 'output.csv' FIELDS TERMINATED BY '|' ENCLOSED BY '"' ESCAPED BY '"' FROM (SELECT... INTO OUTFILE 'output.csv' FIELDS TERMINATED BY '|' ENCLOSED BY '"' ESCAPED BY '"' FROM (SELECT...

Этот проект имеет несколько тестов интеграции Java для этого процесса. Эти тесты в основном зеленые, но иногда они терпят неудачу с:

  • SQLException: Невозможно создать/записать в файл '… (код ошибки: 2 - такого файла или каталога нет)
  • SQLException: Невозможно получить статистику '… Errcode: 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)

Файл .csv внутри контейнера datahub, показывает следующее, fo ls -lha

[email protected]:/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 как корень

Выход:

[email protected]:/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 с MacOs и подключенного тома.

4b9b3361

Ответ 1

Возможно, вы пытаетесь получить доступ к файлу, который находится за пределами стандартных путей docker по умолчанию для mac (из документации docker osx)

По умолчанию вы можете совместно использовать файлы в /Users/,/Volumes/,/private/и /tmp. Чтобы добавить или удалить деревья каталогов, экспортированные в Docker, используйте вкладку "Общий доступ к файлам" в меню "Настройки докеров" → "Настройки" → "Обмен файлами". (См. "Настройки".)

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

В случае, докер для mac использует виртуальную машину linux, запущенную hyperkit в Mac OS. Клиент работает на macOSx и демоне в виртуальной машине. Это объясняет, что вы должны делиться файлами в ограниченном списке путей.

Ответ 2

Мне кажется, что вы, вероятно, сталкиваетесь здесь с двумя отдельными проблемами, обе из которых связаны с настройкой сервера MySQL.

Сервер MySQL работает с параметром --secure-file-priv, поэтому не может выполнить это утверждение.

Этот параметр требует, чтобы любая загрузка файла или экспорт файла были помещены в указанное место хранения в файловой системе. Вы можете найти местоположение с помощью следующей команды из клиента командной строки MySQL или из MySQL Workbench:

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

Результат этого должен определить местоположение, куда файлы могут быть загружены и записаны. Никакое другое местоположение не должно быть разрешено, если включена функция secure-file-priv.

(Ошибка чтения пакетов связи)

Это часто вызвано тем, что загружаемые или экспортируемые данные превышают максимальный размер пакета MySQL.

Аналогичным образом вы можете найти значение для максимального разрешенного пакета, используя следующую команду из клиента командной строки MySQL или из MySQL Workbench:

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

В работающем экземпляре MySQL:

SET GLOBAL max_allowed_packet = 268435456;

(перезапуск службы не требуется.)

Кроме того, используемой учетной записи MySQL должно быть предоставлено разрешение "ФАЙЛ" для загрузки или экспорта. Поскольку вы используете корневую (административную) учетную запись MySQL, это не должно быть фактором, но я подумал, что включу его для всех, кто сталкивается с этим.

Надеюсь, это поможет.

Ответ 3

Я думаю, что у вас есть проблемы с разрешением обмениваться папками между контейнерами Docker и хостом Вам необходимо сопоставить пользователей контейнеров с пользователями хоста, задав UID в файле .env.

UID = 501 # запустить echo $ UID, чтобы получить идентификатор текущего пользователя

версия: "3" Сервисы:   datahub_db:     изображение: "mysql: 5.7.20"     пользователь: $ UID     перезагрузка: всегда     окружающая обстановка:       - MYSQL_ROOT_PASSWORD = $ {DATAHUB_DB_ROOT_PASSWORD}       - MYSQL_DATABASE = $ {DATAHUB_DB_DATABASE}     объемы:       - "datahub_db: /var/lib/mysql"       - "./data/datahub/import: /var/lib/mysql-files/datahub/import"       - "./data/akeneo/import: /var/lib/mysql-files/akeneo/import"     порты:       - "$ {DATAHUB_DB_PORT}: 3306"

...

объемы: datahub_db: