Rimuovere la clausola DEFINER dai dump MySQL


114

Ho un dump MySQL di uno dei miei database. In esso ci sono clausole DEFINER che assomigliano a,

"DEFINER=`root`@`localhost`" 

Vale a dire, queste clausole DEFINER si trovano nelle mie istruzioni CREATE VIEW e CREATE PROCEDURE. C'è un modo per rimuovere queste clausole DEFINER dal mio file di dump?


Un bug è stato segnalato anni fa, ma sembra abbandonato: bugs.mysql.com/bug.php?id=24680
1234ru

Risposte:


109

Non credo che ci sia un modo per ignorare l'aggiunta di messaggi di posta DEFINERelettronica al dump. Ma ci sono modi per rimuoverli dopo aver creato il file di dump.

  1. Apri il file di dump in un editor di testo e sostituisci tutte le occorrenze di DEFINER=root@localhostcon una stringa vuota ""

  2. Modificare il dump (o reindirizzare l'output) utilizzando perl:

    perl -p -i.bak -e "s/DEFINER=\`\w.*\`@\`\d[0-3].*[0-3]\`//g" mydatabase.sql
  3. Indirizza l'output attraverso sed:

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

1
@ FastTrack, rimuovi l'intera stringa.
Abhay

3
Suggerisco di menzionare che invece di rimuovere il DEFINER può essere impostato su CURRENT_USER in questo modo: sed -E 's/DEFINER=[^ ]+@ [^] + /DEFINER=CURRENT_USER/g' dump.sql > new_dump.sqlHa il vantaggio di mantenere restrizioni / controllo di accesso.
4thfloorstudios

27
Il sedcomando non rimuove la clausola DEFINER dalle procedure e dalle funzioni. Ecco la versione migliorata che gestisce visualizzazioni, trigger, procedure e funzioni: sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*PROCEDURE/PROCEDURE/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*FUNCTION/FUNCTION/'
Vladimir Strugatsky

4
Cordiali saluti --- sebbene non fosse il caso al momento di questa risposta, MySQL> 5.6 ora viene fornito con un mysqldump (1) che supporta "--skip-definer" come opzione: dev.mysql.com/doc/refman /5.7/en/…
Kevin_Kinsey

4
No, non è mysqldump, ma mysql p ump che ha --skip-definer.
Xdg

70

Puoi rimuovere usando SED

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

In MacOS:

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

Cosa sta succedendo qui in MacOS per essere diverso?
Alex

1
La pagina di manuale di sed su mac dice: -i extension"Modifica i file sul posto, salvando i backup con l'estensione specificata. Se viene fornita un'estensione di lunghezza zero, non verrà salvato alcun backup. Non è consigliabile fornire un'estensione di lunghezza zero quando modificare i file sul posto, poiché si rischia il danneggiamento o il contenuto parziale in situazioni in cui lo spazio su disco è esaurito, ecc. "
Ciad

Bello saperlo, @Chad. Sto usando sed in questo modo su Mac da più di 5 anni. Non ho mai avuto problemi di spazio o file danneggiati. Ma ovviamente è qualcosa da considerare. Grazie per il chiarimento.
Ricardo Martins,

Non ho mai incontrato questi problemi nemmeno su Mac. Ho solo pensato di chiarire dato che @Alex ha chiesto :)
Ciad

57

Dalla versione 5.7.8 di mysql puoi usare l' --skip-defineropzione con mysqlpump, ad esempio:

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

Vedere il manuale mysql aggiornato su http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html#option_mysqlpump_skip-definer


8
Per chi si chiede qual è la differenza tra mysqldumpe mysqlpump- ecco la domanda correlata: dba.stackexchange.com/questions/118846/mysqldump-vs-mysqlpump
Scadge

Ho installato phpMyAdmin e MySQL Workbench. Come eseguo questo comando su Windows?
posfan12

(dopo alcuni test: -1) Usa information_schema.user, e questo non è sempre leggibile per tutti gli utenti
bato3

17

Ho usato queste idee per rimuovere la clausola DEFINER dal mio output di mysqldump, ma ho adottato un approccio più semplice:

Basta rimuovere la !prima del codice e DEFINER e il resto del commento diventa un normale commento.

Esempio:

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

è reso impotente, anche solo facendo questo ..

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

L'espressione regolare più semplice, tuttavia, è rimuovere il! e i numeri

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

Questo rimuove !#### DEFINERe sostituisce DEFINER ... potresti rimuovere anche DEFINER, non ha molta importanza - una volta che il "!" è andato


16

Secondo le raccomandazioni dell'altro, ecco un esempio di come rimuovere DEFINER dal dump, dopo che il dump è terminato:

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

4
Per i trigger, le linee sono simili a / *! 50003 CREATE * / / *! 50017 DEFINER = user@ localhost* / / *! 50003 trigger my_triggername BEFORE INSERT ON my_table FOR EACH ROW .... * / ;; e grep -veliminerà completamente quelle righe. (anche se 50017! = 50013)
Kenney

13

Come altri hanno già detto, rimuovere il definitore con qualsiasi tipo di espressione regolare non è troppo complesso. Ma gli altri esempi mi hanno tolto le definizioni delle viste.

Questa è l'espressione regolare che ha funzionato per me:

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

E più velocemente ^^ Grazie
Kevin Labécot

1
Non funziona con i trigger: rimuove anche il file */. MySQL 5.6.31.
Franc Drobnič

10

Per una soluzione automatizzata, potresti guardare mysqlmigrate. È un wrapper Bash mysqldumpche ti consente di migrare i database e ignorare le istruzioni DEFINER. Esempio:

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

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

Altrimenti, sì, è necessario un comando come fa notare Abhay:

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

6

Un'altra opzione su OSX per rimuovere i definitori nel file:

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

5

Dovresti guardare la risposta qui: /dba/9249/how-do-i-change-the-definer-of-a-view-in-mysql/29079#29079

Il modo migliore secondo me per affrontare questo problema, non è aggiungere un'analisi extra della stringa con sed o grep o qualsiasi altro, invece mysqldump è in grado di generare un buon dump aggiungendo --single-transaction


Perché downvoted? Perché questa risposta non è considerata utile?
Jose Nobile

1
La tua risposta ha ancora bisogno di circa 90 voti positivi per ottenere la posizione che merita. Hai il mio :)
Patrick van Bergen

4

Un modo rapido per farlo è reindirizzare l'output di mysqldump attraverso sed per rimuovere le DEFINERistruzioni racchiuse nei commenti condizionali. Lo uso per rimuovere DEFINERdalle CREATE TRIGGERistruzioni, ma puoi modificare il numero di versione del commento sulla condizione nella regex per adattarlo ai tuoi scopi.

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

1
Un'istruzione sed leggermente più leggibile: sed "s / DEFINER (. *?) FUNCTION / FUNCTION /"
reustmd

4

Non sono sicuro che sia d'aiuto, ma uso SQLyog Community Edition, disponibile su: -

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

Quando si scarica sql o si copia su un altro database, è possibile "Ignorare DEFINER"

È gratuito e fornisce le funzionalità di base richieste da molte persone

C'è anche una versione a pagamento disponibile da: -

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

Saluti


Piuttosto che contrassegnare semplicemente come "non utile" forse sarebbe più utile se rispondessi con il motivo per cui ritieni che non sia utile?
Itfidds

3

Per me, questo funziona: perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp. Questo ha rimosso DEFINER = root @ localhost dal mio dump, su ogni dichiarazione della procedura di creazione


2

Ecco una soluzione funzionante completa per rimuovere le informazioni di DEFINER per MySQL 5.6.xe Linux (testato suCentOS 6.5 ).

Usualmente dobbiamo sostituire le seguenti voci da Mysql dump (se prese insieme a dati e trigger / routine / funzioni).

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

Il dump è stato eseguito con il comando mysqldump di seguito.

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

Il file di dump richiesto senza informazioni su DEFINER può essere ottenuto con i seguenti tre comandi.

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

Se il file di dump si trova nella cartella corrente, ignorare [PATH /].

Se i dati nelle tabelle sono molto grandi, prendi il dump in due file, in un file dump prendi il dump con i dati e in un altro file dump esegui il dump solo degli script (Trigger / Funzioni / Procedure.) Ed esegui i tre precedenti comandi sul secondo file di dump (script).


1

Sostituisci tutti i tuoi utenti definer con CURRENT_USER. Nel mio script gradle che crea il backup, il mio script di sostituzione ha il seguente aspetto:

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

che in realtà sta solo chiamando ANT. Allora non dovrai preoccupartene.


1

Su macchine Linux puoi usare questa riga:

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

Devi solo sostituire le stringhe in grassetto con le credenziali utente del database e il nome del database / modello simile.

Maggiori informazioni qui: http://blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/


1

L'unico modo per farlo funzionare sotto Windows:

Installa http://gnuwin32.sourceforge.net/ per avere sed nella riga di comando e aggiungilo al PERCORSO di Windows : D: \ programmi \ 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

Grazie a tutti per i suggerimenti. Essendo pigro, ho scritto uno script chiamato: "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

Per qualcosa come:

DELIMITER ;;
CREATE DEFINER = `mydb` @` localhost` FUNZIONE `miafunzione` () RITORNA int (11)
inizio
(...)
fine ;;

Prova questo:

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

1
  1. apri il tuo database con qualsiasi editor, io l'ho usato con notepad ++,

  2. trova tutto testalo DEFINER=root@localhost e sostituiscilo con nothing ( "") IE. Cancellalo.

Quindi puoi importarlo in qualsiasi host tu voglia.


0

La regex più semplice che funziona per me con tutti gli oggetti è:

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

Nota che quote-namesdeve essere TRUE(che è l'impostazione predefinita).

Spero che nelle versioni più recenti lo switch --skip-definerintrodotto in mysqlpump nella versione 5.7 arrivi anche a mysqldump.


0

Ho usato lo script PowerShell per rimuovere tutte le righe con DEFINER :

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


0

Niente funzionava per me, quindi avevo bisogno di scrivere la mia regex.

  1. Prova a eseguire il dump del tuo database in un file, un catintero file e grepsolo le tue dichiarazioni di definizione per vederli.

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

  2. Scrivi la tua regex

  3. Conduci la tua discarica in sed con questa regex. Ad esempio, la mia dichiarazione è:

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

  4. Profitto!


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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.