Удалить предложение DEFINER из дампов MySQL
У меня есть дамп MySQL одной из моих баз данных. В нем есть предложения DEFINER, которые выглядят так:
"DEFINER=`root`@`localhost`"
А именно, эти предложения DEFINER включены в мои операторы CREATE VIEW и CREATE PROCEDURE. Есть ли способ удалить эти предложения DEFINER из моего файла дампа?
30 ответов
Я не думаю, что есть способ игнорировать добавление DEFINER
с на свалку. Но есть способы удалить их после создания файла дампа.
Откройте файл дампа в текстовом редакторе и замените все вхождения
DEFINER=root@localhost
с пустой строкой ""Отредактируйте дамп (или передайте вывод), используя
perl
:perl -p -i.bak -e "s/DEFINER=\`\w.*\`@\`\d[0-3].*[0-3]\`//g" mydatabase.sql
Труба вывод через
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
откройте свою базу данных любым редактором, который я использовал с notepad++,
найти все тесты, которые
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/
У меня ничего не получалось, поэтому мне нужно было написать собственное регулярное выражение.
Попробуйте сбросить вашу базу данных в файл,
cat
весь файл иgrep
только ваши определенные заявления, чтобы увидеть их.кошка file.sql | grep -o -E '.{,60}DEFINER.{,60}'
Напишите свое регулярное выражение
Скопируйте свой дамп в sed с помощью этого регулярного выражения. Например, мое заявление:
mysqldump | sed -E ///! 500 [0-9] [0-9] DEFINER =. +? * /// '| sed -E 's / DEFINER =
?[^ ]+?
? @?[^ ]+?
//?"Прибыль!
Просто на будущее,
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"
Объяснение:
- DEFINER {потенциальные пробелы} = {потенциальные пробелы}…
- … {Любая потенциальная цитата или обратная кавычка, записано}…
- (прервать последовательность, добавить экранированную одинарную кавычку, возобновить последовательность - потому что мы заключаем конструкцию в одинарные кавычки)
- … (Имя пользователя) {строка: без кавычек или @}…
- … {Используйте первую группу захвата - цитату - если есть}…
- … {Потенциальные пробелы} @ {потенциальные пробелы}…
- … {То же самое для хоста с новой группой захвата, но без звездочки}.
(Запустите без строки объяснения с комментариями, потому что это приведет к ошибке)
Мое решение для удаления проверено на моем 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