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


115

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

"DEFINER=`root`@`localhost`" 

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


Об ошибке сообщили много лет назад, но она выглядит заброшенной: bugs.mysql.com/bug.php?id=24680
1234ru

Ответы:


109

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

  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

1
@FastTrack, пожалуйста, удалите всю строку.
Abhay

3
Я предлагаю упомянуть, что вместо удаления DEFINER он может быть установлен на CURRENT_USER следующим образом: sed -E 's/DEFINER=[^ ]+@ [^] + /DEFINER=CURRENT_USER/g' dump.sql > new_dump.sqlОн имеет то преимущество, что сохраняет ограничения / контроль доступа.
4thfloorstudios

27
Команда sedне удаляет предложение DEFINER из процедур и функций. Вот расширенная версия, которая обрабатывает представления, триггеры, процедуры и функции: sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*PROCEDURE/PROCEDURE/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*FUNCTION/FUNCTION/'
Владимир Стругацкий

4
К вашему сведению - хотя на момент этого ответа это было не так, MySQL> 5.6 теперь поставляется с mysqldump (1), который поддерживает «--skip-Definer» в качестве опции: dev.mysql.com/doc/refman /5.7/en/…
Kevin_Kinsey

4
Нет, это не mysqldump, а mysql p ump, у которого есть --skip-Definer.
Xdg

70

Убрать можно с помощью SED

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

В MacOS:

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

Что здесь, в MacOS, должно отличаться?
Alex

1
На странице руководства для sed на Mac говорится следующее: -i extension«Редактируйте файлы на месте, сохраняя резервные копии с указанным расширением. Если задано расширение нулевой длины, резервная копия не будет сохранена. Не рекомендуется указывать расширение нулевой длины, когда редактирование файлов на месте, поскольку вы рискуете повредить или частично содержимое в ситуациях, когда дисковое пространство исчерпано и т.д.
Чад

Приятно это знать, @Chad. Я использую sed в Mac вот уже 5+ лет. У меня никогда не было проблем с пространством или поврежденными файлами. Но, конечно, есть над чем подумать. Спасибо за разъяснение.
Рикардо Мартинс,

Я никогда не сталкивался с этими проблемами на Mac. Просто подумал, что я уточню, так как @Alex спросил :)
Чад

57

Начиная с версии 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#option_mysqlpump_skip-definer


8
Для тех, кто задается вопросом, в чем разница между mysqldumpи mysqlpump- вот связанный с этим вопрос: dba.stackexchange.com/questions/118846/mysqldump-vs-mysqlpump
Scadge

У меня установлены phpMyAdmin и MySQL Workbench. Как мне выполнить эту команду в Windows?
posfan12

(после некоторых тестов: -1) Используется information_schema.user, и это не всегда доступно для чтения всем пользователям
bato3 07

17

Я использовал эти идеи, чтобы удалить предложение 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, на самом деле это не имеет значения - как только "!" ушел


16

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

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

4
Для триггеров строки выглядят следующим образом: / *! 50003 CREATE * / / *! 50017 DEFINER = user@ localhost* / / *! 50003 trigger my_triggername BEFORE INSERT ON my_table FOR EACH ROW .... * / ;; и grep -vполностью отбросит эти строки. (хотя 50017! = 50013)
Кенни

13

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

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

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

И быстрее ^^ Спасибо
Кевин Лабекот

1
Не работает с триггерами - убирает и */. MySQL 5.6.31.
Франк Дробнич

10

Для автоматизированного решения вы можете посмотреть 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

6

Другой вариант в OSX для удаления определителей в файле:

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

5

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

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


Почему проголосовали против? Почему этот ответ не считается полезным?
Хосе Нобиле

1
Вашему ответу по-прежнему нужно около 90 голосов, чтобы занять заслуженную позицию. У тебя есть мой :)
Патрик ван Берген

4

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

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

1
Немного более читаемый оператор sed: sed "s / DEFINER (. *?) FUNCTION / FUNCTION /"
reustmd

4

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

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

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

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

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

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

ура


Возможно, будет полезнее, чем просто пометить как «бесполезно», если вы ответите, почему вы считаете это бесполезным?
itfidds

3

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


2

Вот полное рабочее решение для удаления информации DEFINER для MySQL 5.6.xLinux и (протестировано 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-м файле дампа (скриптов).


1

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

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

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


1

На машинах 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

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

Установите http://gnuwin32.sourceforge.net/, чтобы в командной строке был sed, и добавьте его в ПУТЬ Windows : 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

1

Спасибо всем за подсказки. Будучи ленивым, я написал сценарий под названием «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

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

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

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

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

1
  1. откройте свою базу данных любым редактором, который я использовал с notepad ++,

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

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


0

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

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

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

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


0

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

get-content $ file_in_full_path | строка выбора -паттерн $ line_string_delete -notmatch | Out-File -width 1000000000 -Encoding Default $ file_out_full_path


0

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

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

    cat file.sql | grep -o -E '. {, 60} ОПРЕДЕЛИТЕЛЬ. {, 60}'

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

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

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

  4. Прибыль!


0

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.