Удалить предложение DEFINER из дампов MySQL

У меня есть дамп MySQL одной из моих баз данных. В нем есть предложения DEFINER, которые выглядят так:

"DEFINER=`root`@`localhost`" 

А именно, эти предложения DEFINER включены в мои операторы CREATE VIEW и CREATE PROCEDURE. Есть ли способ удалить эти предложения DEFINER из моего файла дампа?

30 ответов

Решение

Я не думаю, что есть способ игнорировать добавление DEFINER с на свалку. Но есть способы удалить их после создания файла дампа.

  1. Откройте файл дампа в текстовом редакторе и замените все вхождения DEFINER=root@localhost с пустой строкой ""

  2. Отредактируйте дамп (или передайте вывод), используя perl :

    perl -p -i.bak -e "s/DEFINER=\`\w.*\`@\`\d[0-3].*[0-3]\`//g" mydatabase.sql
    
  3. Труба вывод через sed:

    mysqldump ... | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > triggers_backup.sql
    

Вы можете удалить с помощью SED

sed -i 's/DEFINER=[^*]*\*/\*/g' mydump.sql

В MacOS:

sed -i '' 's/DEFINER=[^*]*\*/\*/g' mydump.sql

Начиная с версии MySQL 5.7.8 вы можете использовать --skip-definer опция с mysqlpump, например:

mysqlpump --skip-definer -h localhost -u user -p yourdatabase

См. Обновленное руководство по mysql по адресу http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html.

Я использовал эти идеи, чтобы убрать предложение DEFINER из моего собственного вывода mysqldump, но я выбрал более простой подход:

Просто удалите ! перед кодом и DEFINER, а остальная часть комментария становится обычным комментарием.

Пример:

/*!50017 DEFINER=`user`@`111.22.33.44`*/

оказывается беспомощным, всего лишь делая это..

/* 50017 DEFINER=`user`@`111.22.33.44`*/

Однако самое простое регулярное выражение - удалить! и цифры

mysqldump | /usr/bin/perl -pe 's/\!\d+ DEFINER/DEFINER/' > dumpfile.sql

Что удаляет !#### DEFINER и заменяет на DEFINER... вы также можете удалить DEFINER, это не имеет значения - один раз "!" ушел

Согласно рекомендациям другого, вот пример того, как удалить DEFINER из дампа после его завершения:

mysqldump -u user --password='password' -h localhost database | grep -v "50013 DEFINER" > dump.sql

Как уже упоминалось, удаление определителя с помощью любого вида регулярных выражений не слишком сложно. Но другие примеры лишают меня определения представлений.

Это регулярное выражение, которое работает для меня:

sed -e 's/DEFINER=[^ ]* / /'

Для автоматизированного решения вы можете посмотреть на mysqlmigrate, Это оболочка Bash вокруг mysqldump что позволяет переносить базы данных и игнорировать операторы DEFINER. Пример:

$ mysqlmigrate -u root -p pass --ignore-definer from_db to_db

http://thesimplesynthesis.com/post/mysqlmigrate (или GitHub)

В противном случае, да, такая команда, как указывает Абхай, необходима:

$ mysqldump -u root -ppass the_db | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > the_db.sql

Вы должны посмотреть ответ здесь: https://dba.stackexchange.com/questions/9249/how-do-i-change-the-definer-of-a-view-in-mysql/29079

На мой взгляд, лучший способ решить эту проблему - не добавлять дополнительный анализ строки с помощью sed, grep или любого другого, вместо этого mysqldump может генерировать хороший дамп, добавив --single -action

Еще одна опция в OSX для удаления определителей в файле:

sed -i '' 's/DEFINER=`[^`][^`]*`@`[^`][^`]*`//g' file.sql

Быстрый способ сделать это - передать вывод mysqldump через sed, чтобы удалить DEFINER заявления завернуты в условные комментарии. Я использую это, чтобы удалить DEFINER от CREATE TRIGGER заявления, но вы можете настроить номер версии комментария условия в регулярном выражении в соответствии с вашими целями.

mysqldump -u user --password='password' -h localhost database | \
  sed 's/\/\*!50017 DEFINER=`.*`@`.*`\*\///' 

Вот полное рабочее решение для удаления информации DEFINER для MySQL 5.6.x и Linux.(Проверено на CentOS 6.5).

Обычно мы должны заменить следующие записи из дампа Mysql (если они взяты вместе с данными и триггерами / процедурами / функциями).

/*!50013 DEFINER=`MYSQLUSER`@`localhost` SQL SECURITY DEFINER */
/*!50013 DEFINER=`MYSQLUSER`@`%` SQL SECURITY DEFINER */
CREATE DEFINER=`MYSQLUSER`@`%` PROCEDURE `PROCEDURENAME`(
CREATE DEFINER=`MYSQLUSER`@`localhost` PROCEDURE `PROCEDURENAME`(
CREATE DEFINER=`MYSQLUSER`@`%` FUNCTION `FUNCTIONNAME`(
CREATE DEFINER=`MYSQLUSER`@`localhost` FUNCTION `FUNCTIONNAME`(
/*!50003 CREATE*/ /*!50017 DEFINER=`MYSQLUSER`@`%`*/ /*!50003 TRIGGER `TRIGGERNAME`
/*!50003 CREATE*/ /*!50017 DEFINER=`MYSQLUSER`@`localhost`*/ /*!50003 TRIGGER `TRIGGERNAME`

Дамп был взят с помощью команды mysqldump.

mysqldump -uMYSQLUSER -pPASSWORD DATABASENAME -R > dbdump.sql

Требуемый файл дампа без информации DEFINER может быть получен с помощью следующих трех команд.

Command-1    
sed -i 's|DEFINER=[^*]*\*|\*|g' [PATH/]dbdump.sql

Command-2
find -name [PATH/]dbdump.sql | xargs perl -pi -e "s/ DEFINER=\`MYSQLUSER\`@\`localhost\`//"

Command-3
find -name [PATH/]dbdump.sql | xargs perl -pi -e "s/ DEFINER=\`MYSQLUSER\`@\`%\`//"

Если файл дампа находится в вашей текущей папке, тогда игнорируйте [PATH/].

Если данные в таблицах очень велики, возьмите дамп в двух файлах, в одном файле дампа возьмите дамп с данными, а в другом файле дампа - только дамп сценариев (Триггеры / Функции / Процедуры.) И запустите три указанных выше. команды на 2-й файл дампа (скрипты).

Не уверен, поможет ли это, но я использую SQLyog Community Edition, доступную по адресу: -

https://code.google.com/p/sqlyog/wiki/Downloads

При выгрузке sql или копировании в другую базу данных вы можете "игнорировать DEFINER"

Это бесплатно и предоставляет основные функции, которые требуются многим людям

Существует также платная версия, доступная от: -

https://www.webyog.com/product/sqlyog

ура

Лучший способ без проблем сбросить и восстановить:

MYSQL DUMP

mysqldump -h HOST -u USER -pPASSWORD --single-transaction --quick --skip-lock-tables --triggers --routines --events DATABASE | gzip > "DATABASE.sql.gz" &

ВОССТАНОВЛЕНИЕ MYSQL

gunzip DATABASE.sql.gz

sed -i 's/DEFINER=[^ ]* / /' DATABASE.sql
sed -i 's/SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;/ /' DATABASE.sql
sed -i 's/SET @@SESSION.SQL_LOG_BIN= 0;/ /' DATABASE.sql
sed -i 's/SET @@GLOBAL.GTID_PURGED='';/ /' DATABASE.sql
sed -i 's/SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN;/ /' DATABASE.sql

mysql -h HOST -u USER -pPASSWORD < DATABASE.sql

если вы уже экспортировали этот файл sql, вы можете изменить DEFINER внутри этого файла, выполнив:

      sed 's/\sDEFINER=`[^`]*`@`[^`]*`//g' -i your_dumpfile.sql

Для меня это работает: perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp, Это удаляло DEFINER=root@localhost из моего дампа при каждой оценке процедуры создания

Как уже говорили другие, одним из возможных решений является замена имен пользователей в предложениях DEFINER на CURRENT_USER.
Обратите внимание, что мы должны учитывать DEFINER как в простых операторах SQL, так и в специальных комментариях, как в следующих примерах:

      CREATE DEFINER=`root`@`localhost` FUNCTION...
/*!50013 DEFINER=`MYSQLUSER`@`%` SQL SECURITY DEFINER */
/*!50017 DEFINER=`root`@`localhost`*/

Итак, для меня работает следующее:

      mysqldump <my-options> | sed -E 's/DEFINER=[^ *]+/DEFINER=CURRENT_USER/g' > dumpfile.sql

Замените всех ваших определенных пользователей на CURRENT_USER. В моем скрипте gradle, который создает резервную копию, мой скрипт замены выглядит так:

ant.replaceregexp(file: "$buildDir/sql/setupDB.sql", match: "`${project.ext.prod_db_username}`@`%`", replace: "CURRENT_USER", byline: true);

который на самом деле просто вызывает ANT. Тогда вам не придется беспокоиться об этом.

Для чего-то вроде:

РАЗДЕЛИТЕЛЬ;;
CREATE DEFINER=`mydb`@`localhost` ФУНКЦИЯ `myfunction`() ВОЗВРАЩАЕТ int(11)
начать
(...)
конец;;

Попробуй это:

mysqldump --force --routines --opt --user = myuser --databases mydb | sed -e 's / DEFINER = `. *` @ `. *` \ // g'

Единственный способ заставить его работать под Windows:

Установите http://gnuwin32.sourceforge.net/ чтобы иметь sed в командной строке, и добавьте его в Windows PATH: D: \ Programs\GetGnuWin32\bin;

sed -i "s|DEFINER=`mydbuser`@`%%` SQL SECURITY DEFINER||g" "D:/prod_structure.sql"

sed -i "s|DEFINER=`mydbuser`@`%%`||g" "D:/prod_structure.sql"

mysqldump -P{port} -h{host} -u{user} -p{password} --routines --no-data --lock-tables=false database_prod > D:\prod_structure.sql

Спасибо всем за подсказки. Будучи ленивым, я написал сценарий под названием "MYsqldump":

DB=$1
HOST=$2
USER=$3
MYSQLDUMP='/usr/bin/mysqldump'
PARAMS="--complete-insert --disable-keys=0 --extended-insert=0 --routines=0 --skip-comments"
DAY=`date +%d`
MONTH=`date +%m`
YEAR=`date +%Y`
FILE=$DB.$DAY-$MONTH-$YEAR.sql

    if (( $# < 3 )) ; then
        echo ""
        echo "usage: MYsqldump <db> <host> <user>"
        echo ""
        exit 1
    fi

    $MYSQLDUMP -h $HOST -u $USER -p  $PARAMS $DB | grep -v '/*!50013 DEFINER' > $FILE
  1. откройте свою базу данных любым редактором, который я использовал с notepad++,

  2. найти все тесты, которые DEFINER=root@localhostи заменить его ничем ("") IE. удали это.

Затем вы можете импортировать его на любой хост, который вы хотите.

На машинах Linux вы можете использовать эту однострочную строку:

mysql -uuser -ppwd -A --skip-column-names -e"SELECT CONCAT('SHOW CREATE VIEW ',table_schema,'.',table_name,';') FROM information_schema.tables WHERE engine IS NULL and table_schema like 'mydb%'" | mysql -uuser -ppwd -A --skip-column-names | sed -rn 's/.*?VIEW ([^\s]+?) (AS .*?)\s([^\s]+?)\s([^\s]+?)/DROP VIEW \1;\nCREATE VIEW \1 \2;/p' | mysql -uuser -ppwd -A --skip-column-names

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

Более подробная информация здесь: http://blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/

У меня ничего не получалось, поэтому мне нужно было написать собственное регулярное выражение.

  1. Попробуйте сбросить вашу базу данных в файл, cat весь файл и grep только ваши определенные заявления, чтобы увидеть их.

    кошка file.sql | grep -o -E '.{,60}DEFINER.{,60}'

  2. Напишите свое регулярное выражение

  3. Скопируйте свой дамп в sed с помощью этого регулярного выражения. Например, мое заявление:

    mysqldump | sed -E ///! 500 [0-9] [0-9] DEFINER =. +? * /// '| sed -E 's / DEFINER =?[^ ]+?? @?[^ ]+? //?"

  4. Прибыль!

Просто на будущее, sd версия.

mysqldump ... | sd 'DEFINER=.*?\*' '*' > file.sql

Я использовал скрипт PowerShell, чтобы удалить все строки с DEFINER:

get-content $ file_in_full_path | select-string -pattern $ line_string_delete -notmatch | Out-File -width 1000000000 -Кодирование по умолчанию $file_out_full_path

Remove _definers.bat:

@echo off
(for /f "tokens=1,2*" %%a in (dumpfile.sql) do (
 if "%%b"=="" (echo %%a) else (
  echo %%b | find "DEFINER" > null && echo %%a %%c || echo %%a %%b %%c
 )
)) > dumpfile_nodefiners.sql

Самое простое регулярное выражение, которое работает для меня со всеми объектами:

sed 's/DEFINER=[^ ]*`//' ...

Обратите внимание, что quote-names должен быть TRUE (что по умолчанию).

Надеюсь, что в более новых версиях коммутатор --skip-definer введенный в mysqlpump в версии 5.7, также подходит и для mysqldump.

Если в вашем файле SQL есть DEFINER случаев (с и) без условных комментариев, то вас может заинтересовать этот альтернативный REGEXP.

      sed -Ei \
    's/DEFINER\s*=\s*(["'\''`]?)[^"'\''`@]+\1\s*@\s*(["'\''`]?)[^"'\''`\*]+\2//g' \
#      [-----1------][----2----][----4----]-5[--6--][----------7------------]
    "$FILE"

Объяснение:

  1. DEFINER {потенциальные пробелы} = {потенциальные пробелы}…
  2. … {Любая потенциальная цитата или обратная кавычка, записано}…
  3. (прервать последовательность, добавить экранированную одинарную кавычку, возобновить последовательность - потому что мы заключаем конструкцию в одинарные кавычки)
  4. (Имя пользователя) {строка: без кавычек или @}…
  5. … {Используйте первую группу захвата - цитату - если есть}…
  6. … {Потенциальные пробелы} @ {потенциальные пробелы}…
  7. … {То же самое для хоста с новой группой захвата, но без звездочки}.

(Запустите без строки объяснения с комментариями, потому что это приведет к ошибке)

Мое решение для удаления проверено на моем MariaDB 10.3:

      mysqldump | grep -v -P 'SQL SECURITY DEFINER \*/$' | perl -pe 's/(?<=^\/\*!50003 CREATE\*\/ )\/\*!50017 DEFINER=`.+`@`.+`\*\/ (?=\/\*!50003 TRIGGER)//'

grep удаляет его для просмотров, perl убирает это для триггеров

Это решение защищено от злоумышленников, поскольку соответствует началу и концу строк. Таким образом, даже если злоумышленник знает, что вы выполняете замену на ваших свалках, его DEFINER расположенные в данных не будут заменены.

Ссылаясь на /questions/12578126/oshibka-mysql-1449-polzovatel-ukazannyij-kak-opredelitel-ne-suschestvuet/12578135#12578135, я подозреваю, что следующее может работать лучше с очень большими базами данных - измените определитель в конце, а не выполняйте дополнительную обработку регулярных выражений в каждой строке:

mysqldump myDB > dump.sql
cat >> dump.sql << END
SELECT CONCAT("ALTER DEFINER=`youruser`@`host` VIEW ", 
table_name, " AS ", view_definition, ";") 
FROM information_schema.views 
WHERE table_schema='myDB';
END
Другие вопросы по тегам