Usuń klauzulę DEFINER ze zrzutów MySQL

114

Mam zrzut MySQL jednej z moich baz danych. Są w nim klauzule DEFINER, które wyglądają jak:

"DEFINER=`root`@`localhost`" 

Mianowicie, te klauzule DEFINER znajdują się w moich instrukcjach CREATE VIEW i CREATE PROCEDURE. Czy istnieje sposób na usunięcie tych klauzul DEFINER z mojego pliku zrzutu?

FastTrack
źródło
Błąd został zgłoszony lata temu, ale wygląda na porzucony: bugs.mysql.com/bug.php?id=24680
1234ru

Odpowiedzi:

109

Nie sądzę, aby można było zignorować dodawanie DEFINERs do zrzutu. Ale istnieją sposoby na ich usunięcie po utworzeniu pliku zrzutu.

  1. Otwórz plik zrzutu w edytorze tekstu i zamień wszystkie wystąpienia DEFINER=root@localhostna pustym ciągiem „”

  2. Edytuj zrzut (lub potokuj wyjście) używając perl:

    perl -p -i.bak -e "s/DEFINER=\`\w.*\`@\`\d[0-3].*[0-3]\`//g" mydatabase.sql
  3. Przepuść wyjście przez sed:

    mysqldump ... | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > triggers_backup.sql
Abhay
źródło
1
@FastTrack, usuń cały ciąg.
Abhay,
3
Proponuję wspomnieć, że zamiast usuwać DEFINER można ustawić go na CURRENT_USER w ten sposób: sed -E 's/DEFINER=[^ ]+@ [^] + /DEFINER=CURRENT_USER/g' dump.sql > new_dump.sqlMa tę zaletę, że utrzymuje ograniczenia / kontrolę dostępu.
4thfloorstudios
27
sedKomenda nie usuwa zapis definiujący od procedur i funkcji. Oto ulepszona wersja, która obsługuje widoki, wyzwalacze, procedury i funkcje: sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*PROCEDURE/PROCEDURE/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*FUNCTION/FUNCTION/'
Vladimir Strugatsky,
4
Do Twojej wiadomości --- chociaż nie było to w momencie tej odpowiedzi, MySQL> 5.6 jest teraz dostarczany z mysqldump (1), który obsługuje "--skip-definer" jako opcję: dev.mysql.com/doc/refman /5.7/en/…
Kevin_Kinsey
4
Nie, to nie mysqldump, ale mysql p ump ma opcję --skip-definer.
Xdg
70

Możesz usunąć za pomocą SED

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

W systemie MacOS:

sed -i '' 's/DEFINER=[^*]*\*/\*/g' mydump.sql
Ricardo Martins
źródło
Co się dzieje w MacOS, żeby było inaczej?
Alex,
1
Strona podręcznika użytkownika seda na komputerze Mac mówi tak: -i extension„Edytuj pliki w miejscu, zapisując kopie zapasowe z określonym rozszerzeniem. Jeśli podano rozszerzenie o zerowej długości, żadna kopia zapasowa nie zostanie zapisana. Nie zaleca się nadawania rozszerzenia o zerowej długości, gdy pliki do edycji lokalnej, ponieważ istnieje ryzyko uszkodzenia lub częściowej zawartości w sytuacjach, gdy miejsce na dysku jest wyczerpane itp. ”
Czad
Miło to wiedzieć, @Chad. Używam seda w ten sposób na Macu od ponad 5 lat. Nigdy nie miałem problemów z przestrzenią lub uszkodzonymi plikami. Ale oczywiście jest coś do rozważenia. Dzięki za wytłumaczenie.
Ricardo Martins
Nigdy też nie napotkałem tych problemów na Macu. Pomyślałem, że wyjaśnię, ponieważ @Alex zapytał :)
Czad
57

Od wersji mysql 5.7.8 możesz użyć tej --skip-defineropcji z mysqlpump, np:

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

Zobacz zaktualizowaną instrukcję mysql na http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html#option_mysqlpump_skip-definer

maxhb
źródło
8
Dla każdego, kto zastanawia się, jaka jest różnica między mysqldumpa mysqlpump- tutaj jest powiązane pytanie: dba.stackexchange.com/questions/118846/mysqldump-vs-mysqlpump
Scadge
Mam zainstalowane phpMyAdmin i MySQL Workbench. Jak wykonać to polecenie w systemie Windows?
posfan12
(po kilku testach: -1) Używa information_schema.useri nie zawsze jest to czytelne dla wszystkich użytkowników
bato3
17

Użyłem tych pomysłów, aby usunąć klauzulę DEFINER z własnego wyniku mysqldump, ale wybrałem prostsze podejście:

Po prostu usuń !przed kodem i DEFINER, a reszta komentarza stanie się zwykłym komentarzem.

Przykład:

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

staje się bezradny, tak mało jak to.

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

Najłatwiejszym regexp jest jednak usunięcie! i liczby

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

To usuwa !#### DEFINERi zastępuje DEFINER ... możesz też usunąć DEFINER, to naprawdę nie ma znaczenia - kiedy "!" przepadło

SitesBySequoia.com
źródło
16

Zgodnie z zaleceniami drugiej strony, oto przykład, jak usunąć DEFINER ze zrzutu po zakończeniu zrzutu:

mysqldump -u user --password='password' -h localhost database | grep -v "50013 DEFINER" > dump.sql
Jonathan
źródło
4
W przypadku wyzwalaczy linie wyglądają następująco: / *! 50003 CREATE * / / *! 50017 DEFINER = user@ localhost* / / *! 50003 wyzwalaj my_triggername BEFORE INSERT ON my_table FOR EACH ROW .... * / ;; i grep -vcałkowicie usunie te linie. (chociaż 50017! = 50013)
Kenney
13

Jak wspominali inni, pozbycie się elementu definiującego jakimkolwiek wyrażeniem regularnym nie jest zbyt skomplikowane. Ale inne przykłady pozbawiły mnie definicji widoku.

Oto wyrażenie regularne, które zadziałało dla mnie:

sed -e 's/DEFINER=[^ ]* / /'
Lajos Veres
źródło
I szybciej ^^ Dzięki
Kevin Labécot
1
Nie działa z wyzwalaczami - usuwa również */. MySQL 5.6.31.
Franc Drobnič
10

Aby uzyskać zautomatyzowane rozwiązanie, możesz spojrzeć na mysqlmigrate. Jest to opakowanie Bash, mysqldumpktóre umożliwia migrację baz danych i ignorowanie instrukcji DEFINER. Przykład:

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

http://thesimplesynthesis.com/post/mysqlmigrate (lub GitHub )

W przeciwnym razie tak, potrzebne jest polecenie takie, jak wskazuje Abhay:

$ mysqldump -u root -ppass the_db | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > the_db.sql
josephdpurcell
źródło
6

Inna opcja na OSX, aby usunąć definicje w pliku:

sed -i '' 's/DEFINER=`[^`][^`]*`@`[^`][^`]*`//g' file.sql
mohrt
źródło
5

Powinieneś poszukać odpowiedzi tutaj: /dba/9249/how-do-i-change-the-definer-of-a-view-in-mysql/29079#29079

Moim zdaniem najlepszym sposobem rozwiązania tego problemu jest nie dodawanie dodatkowej analizy ciągu z sed, grep lub jakimkolwiek innym, zamiast tego mysqldump jest w stanie wygenerować dobry zrzut, dodając --single-transaction

Jose Nobile
źródło
Dlaczego odrzucono? Dlaczego ta odpowiedź nie jest uważana za przydatną?
Jose Nobile,
1
Twoja odpowiedź nadal wymaga około 90 głosów za, aby uzyskać pozycję, na jaką zasługuje. Masz moje :)
Patrick van Bergen,
4

Szybkim sposobem na zrobienie tego jest potokowanie wyjścia mysqldump przez sed, aby usunąć DEFINERinstrukcje opakowane w komentarze warunkowe. Używam tego do usuwania DEFINERz CREATE TRIGGERinstrukcji, ale możesz dostosować numer wersji komentarza warunku w wyrażeniu regularnym, aby odpowiadał swoim celom.

mysqldump -u user --password='password' -h localhost database | \
  sed 's/\/\*!50017 DEFINER=`.*`@`.*`\*\///' 
Paul Dixon
źródło
1
Nieco bardziej czytelne stwierdzenie sed: sed "s / DEFINER (. *?) FUNCTION / FUNCTION /"
reustmd
4

Nie wiem, czy to pomaga, ale używam SQLyog Community Edition, dostępnego pod adresem: -

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

Podczas zrzucania sql lub kopiowania do innej bazy danych umożliwia `` Ignoruj ​​DEFINER ''

Jest bezpłatny i zapewnia podstawową funkcjonalność, której wymaga wiele osób

Dostępna jest również wersja płatna: -

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

Twoje zdrowie

itfidds
źródło
Zamiast tylko oznaczać jako „nieprzydatne”, może lepiej byłoby, gdybyś odpowiedział, dlaczego uważasz, że nie jest to przydatne?
itfidds
3

Dla mnie to działa: perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp. To usunęło DEFINER = root @ localhost z mojego zrzutu przy każdej instrukcji tworzenia procedury

Rafwell
źródło
2

Oto kompletne działające rozwiązanie do usuwania informacji DEFINER dla MySQL 5.6.xsystemu i Linux (testowane na CentOS 6.5).

Zwykle musimy zastąpić następujące wpisy ze zrzutu Mysql (jeśli są wzięte razem z danymi i wyzwalaczami / procedurami / funkcjami).

/*!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`

Zrzut został wykonany za pomocą poniższego polecenia mysqldump.

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

Wymagany plik zrzutu bez informacji DEFINER można uzyskać za pomocą poniższych trzech poleceń.

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\`@\`%\`//"

Jeśli plik zrzutu znajduje się w Twoim bieżącym folderze, zignoruj ​​[PATH /].

Jeśli dane w tabelach są bardzo duże, wykonaj zrzut w dwóch plikach, w jednym pliku zrzutu weź zrzut z danymi, aw innym pliku zrzutu weź zrzut tylko skryptów (Wyzwalacze / Funkcje / Procedury.) I uruchom trzy powyższe polecenia w drugim pliku zrzutu (skryptów).

I Bajwa PHD
źródło
1

Zamień wszystkich zdefiniowanych użytkowników na CURRENT_USER. W moim skrypcie Gradle, który tworzy kopię zapasową, mój skrypt zamiany wygląda następująco:

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

który tak naprawdę po prostu dzwoni do ANT. Wtedy nie będziesz musiał się tym martwić.

Ryan Shillington
źródło
1

Na komputerach z systemem Linux możesz użyć tego jednowierszowego:

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

Musisz tylko zamienić pogrubione ciągi na poświadczenia użytkownika bazy danych i nazwę / podobny wzorzec bazy danych.

Więcej informacji tutaj: http://blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/

Novoj
źródło
1

Jedyny sposób, w jaki mogłem go uruchomić pod Windows:

Zainstaluj http://gnuwin32.sourceforge.net/, aby mieć seda w linii poleceń i dodaj go do ŚCIEŻKI Windows : D: \ programy \ 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
Artur Kędzior
źródło
1

Dziękuję wszystkim za podpowiedzi. Będąc leniwy, napisałem skrypt o nazwie: „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
R.Canaro
źródło
1

Na coś takiego:

DELIMITER ;;
CREATE DEFINER = `mydb` @` localhost` FUNCTION `myfunction` () RETURNS int (11)
zaczynać
(...)
koniec ;;

Spróbuj tego:

mysqldump --force --routines --opt --user = myuser --databases mydb | sed -e 's / DEFINER = `. *` @ `. *` \ // g'
impactaweb
źródło
1
  1. otwórz swoją bazę danych dowolnym edytorem, którego używałem z notatnikiem ++,

  2. znajdź wszystko, przetestuj to DEFINER=root@localhost i zamień na none ( "") IE. Usuń to.

Następnie możesz zaimportować go do dowolnego hosta, który chcesz.

Lê Công Danh
źródło
0

Najprostszym wyrażeniem regularnym, które działa dla mnie ze wszystkimi obiektami, jest:

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

Zauważ, że quote-namesmusi być TRUE(co jest domyślne).

Mam nadzieję, że w nowszych wersjach przełącznik --skip-definerwprowadzony w mysqlpump w wersji 5.7 dotyczy również mysqldump.

Franc Drobnič
źródło
0

Użyłem skryptu PowerShell, aby usunąć wszystkie linie z DEFINER:

get-content $ file_in_full_path | select-string -pattern $ line_string_delete -notmatch | Out-File -width 1000000000 -Encoding Domyślnie $ file_out_full_path

Alen
źródło
0

Nic dla mnie nie działało, więc musiałem napisać własny regex.

  1. Spróbuj zrzucić bazę danych do pliku, catcałego pliku i greptylko zdefiniowanych instrukcji, aby je zobaczyć.

    cat plik.sql | grep -o -E '. {, 60} DEFINER. {, 60}'

  2. Wpisz swoje wyrażenie regularne

  3. Prześlij zrzut do seda za pomocą tego wyrażenia regularnego. Na przykład moje stwierdzenie to:

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

  4. Zysk!

Xdg
źródło
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
Luiz Rodolfo
źródło