Код ошибки MySQL 2 в скрипте Perl

#mysql #windows #linux #perl #dbd

#mysql #Windows #linux #perl #dbd

Вопрос:

Я создал инструмент ETL на Perl. Есть три сервера баз данных, с которыми взаимодействует инструмент ETL, скажем, dbserver1 (OLTP-сервер — Windows Box), dbserver2 (промежуточный сервер — Linux Box), dbserver3 (OLAP-сервер, Linux Box). Мой скрипт ETL находится на сервере dbserver 2.

Скрипты считывают данные с сервера dbserver1 и переносят их на сервер dbserver2 для некоторых trnsformations, выполняют преобразования, а затем помещают данные на сервер dbserver3. Для достижения этого скрипт создает некоторые ИСХОДЯЩИЕ данные на сервере dbserver2. Итак, существует два типа запросов на вывод файлов:

  1. Запрос ВЫХОДНОГО файла, который выполняется на сервере dbserver1, создает .данные на сервере dbserver2 и
  2. Создается запрос OUTFILE, который выполняется на сервере dbserver2.файл данных на сервере dbserver2.

Второй запрос работает нормально, поскольку он создает файл на том же сервере. Но первый тип запроса выдает мне следующую ошибку:

 DBD::mysql::st execute failed: Can't create/write to file 'homedbserver2dumpfile.2011-11-04-03:02.data' (Errcode: 2) at stagingtransform.pl line 223, <> line 8.
  

Я предполагаю, что это связано с некоторыми разрешениями пользователя. И если я не ошибаюсь, тогда MySQL на сервере dbserver2 имеет разрешения на чтение / запись на сервер dbserver2, а MySQL на сервере dbserver1 — нет.

Может ли это быть из-за того, что dbserver1 — это Windows, а dbserver2 — это Linux box?

Как я могу это решить?

К вашему сведению: формат файла: dumpfile.гггг-мм-дд-чч:mm.data и я также установил настройки AppArmor для MySQL на сервере dbserver2, который предназначен для MySQL на сервере dbserver2.

Ответ №1:

Проблема в том, что запрос outfile на dbserver1 может записываться только локально, поэтому вам нужен другой подход.
Один очень простой метод заключается в использовании mysqldump (на dbserver2) для подключения к dbserver1 и передачи выходных данных клиенту mysql, который вводит SQL в dbserver2.

С другой стороны, если вы хотите использовать DBI :

 my $source_sql = q{SELECT ...};
my $target_sql = q{INSERT ... VALUES (?, ?, ...)};
my $source = $source_dbh->prepare($source_sql);
my $target = $target_dbh->prepare($target_sql);
$source->execute;
my $qty = $target->execute_array({ArrayTupleFetch => $source});
  

Для больших объемов передачи данных mysqldump подход выполняется быстрее.

Комментарии:

1. Спасибо niczero. data огромен, поскольку в нем около 20 миллионов записей, и, я думаю, это будет действительно медленнее, если я использую вышеуказанный подход… Также mysqldump потребует времени для импорта с dbserver1 на dbserver2. И будет утомительно иметь mysqldump между операциями инструментов ETL. Нет проблемы. Я попробую это.

2. еще одна вещь, dbserver2 имеет запрос OUTFILE, данные которого ETL запишет на dbserver3 с использованием INFILE. Это вызовет какие-либо проблемы с разрешениями, подобные этому для OUTFILE?

3. Да, точно такая же проблема. Другой подход заключался бы в том, чтобы выполнять чтение / запись локально, используя ваш первый метод, но завернутый в скрипт, который затем передает файлы на следующий сервер.

4. Спасибо niczero. Я использовал system (mysql -e «query») и это решило мою проблему. Теперь я могу импортировать данные с dbserver1 на dbserver2, не сильно изменяя свой ETL. Также я использовал LOCAL в запросах, которые импортируют данные с dbserver2 на dbserver3, поскольку мой инструмент ETL находится на dbserver2 и действует как клиент. Итак, это сработало.