Видаліть пункт DEFINER з дампів MySQL


114

У мене є дамп 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, видаліть весь рядок.
Абхай

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
FYI --- хоча під час цієї відповіді це було не так, MySQL> 5.6 тепер постачається з mysqldump (1), який підтримує опцію "--skip-definer": dev.mysql.com/doc/refman /5.7/uk/…
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, щоб бути іншим?
Алекс

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/uk/mysqlpump.html#option_mysqlpump_skip-definer


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

У мене встановлені phpMyAdmin та MySQL Workbench. Як виконати цю команду в Windows?
posfan12

(після декількох тестів: -1) Він використовує information_schema.user, і це не завжди читається для всіх користувачів
bato3

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 спрацьовує my_triggername ПЕРЕД ВСТАВЛЕННЯ НА my_table ЗА ВСІХ РЯДОМ. * / ;; і 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-транзакції


Чому відмовились? Чому ця відповідь не вважається корисною?
Хосе Нобіле

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/Завантажити

Під час скидання 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 та LinuxCentOS 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

Вам потрібно лише замінити рядки жирним шрифтом з вашими обліковими записами користувачів DB та назвою бази даних / подібним шаблоном.

Більше інформації тут: http://blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/


1

Єдиний спосіб, коли я міг би його працювати під 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

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` FUNCTION `myfunction` () ПОВЕРНУЄ int (11)
почати
(...)
кінець ;;

Спробуйте це:

mysqldump --force --routines --opt --user = myuser --дані бази mydb | sed -e 's / DEFINER = `. *` @ `. *` \ // g'

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

  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 | select-string -pattern $ line_string_delete -notmatch | Вихідний файл -ширина 1000000000 -кодування за замовчуванням $ file_out_full_path


0

Ніщо не працювало для мене, тому мені потрібно було написати власний регекс.

  1. Спробуйте скинути вашу базу даних у файл, catцілий файл і grepлише ваші визначені твердження, щоб побачити їх.

    кішка file.sql | grep -o -E '. {, 60} DEFINER. {, 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.