Remova a cláusula DEFINER dos Dumps do MySQL

114

Eu tenho um despejo do MySQL de um dos meus bancos de dados. Nele, existem cláusulas DEFINER que se parecem com,

"DEFINER=`root`@`localhost`" 

Ou seja, essas cláusulas DEFINER estão em minhas instruções CREATE VIEW e CREATE PROCEDURE. Existe uma maneira de remover essas cláusulas DEFINER do meu arquivo de despejo?

Faixa rápida
fonte
Um bug foi relatado anos atrás, mas parece abandonado: bugs.mysql.com/bug.php?id=24680
1234ru

Respostas:

109

Não acho que haja uma maneira de ignorar a adição de DEFINERs ao dump. Mas há maneiras de removê-los após a criação do arquivo de despejo.

  1. Abra o arquivo de despejo em um editor de texto e substitua todas as ocorrências de DEFINER=root@localhostpor uma string vazia ""

  2. Edite o dump (ou canalize a saída) usando perl:

    perl -p -i.bak -e "s/DEFINER=\`\w.*\`@\`\d[0-3].*[0-3]\`//g" mydatabase.sql
  3. Canalize a saída através de sed:

    mysqldump ... | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > triggers_backup.sql
Abhay
fonte
1
@FastTrack, remova a string inteira.
Abhay
3
Sugiro mencionar que ao invés de remover o DEFINER ele pode ser configurado para CURRENT_USER assim: sed -E 's/DEFINER=[^ ]+@ [^] + /DEFINER=CURRENT_USER/g' dump.sql > new_dump.sqlTem a vantagem de manter restrições / controle de acesso.
4thfloorstudios
27
O sedcomando não remove a cláusula DEFINER de procedimentos e funções. Aqui está a versão aprimorada que lida com visualizações, gatilhos, procedimentos e funções: sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*PROCEDURE/PROCEDURE/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*FUNCTION/FUNCTION/'
Vladimir Strugatsky,
4
Para sua informação --- embora não fosse o caso no momento desta resposta, o MySQL> 5.6 agora vem com um mysqldump (1) que suporta "--skip-definer" como uma opção: dev.mysql.com/doc/refman /5.7/en/…
Kevin_Kinsey
4
Não, não é o mysqldump, mas o mysql p ump que possui --skip-definer.
Xdg
70

Você pode remover usando SED

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

Em MacOS:

sed -i '' 's/DEFINER=[^*]*\*/\*/g' mydump.sql
Ricardo Martins
fonte
O que está acontecendo aqui no MacOS para ser diferente?
Alex
1
A página de manual do sed no mac diz o seguinte: -i extension"Editar arquivos no local, salvando backups com a extensão especificada. Se uma extensão de comprimento zero for fornecida, nenhum backup será salvo. Não é recomendado fornecer uma extensão de comprimento zero quando arquivos de edição no local, pois você corre o risco de corromper ou conteúdo parcial em situações em que o espaço em disco se esgota, etc. "
Chade
É bom saber disso, @Chad. Estou usando o sed assim no mac há mais de 5 anos. Nunca tive problemas com espaço ou arquivos corrompidos. Mas, claro, é algo a se considerar. Obrigado por esclarecer.
Ricardo Martins
Também nunca tive esses problemas no Mac. Só pensei em esclarecer, já que @Alex perguntou :)
Chad
57

Desde a versão 5.7.8 do mysql você pode usar a --skip-defineropção com mysqlpump, por exemplo:

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

Consulte o manual atualizado do mysql em http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html#option_mysqlpump_skip-definer

maxhb
fonte
8
Para quem quer saber qual é a diferença entre mysqldumpe mysqlpump- aqui está a pergunta relacionada: dba.stackexchange.com/questions/118846/mysqldump-vs-mysqlpump
Scadge
Tenho phpMyAdmin e MySQL Workbench instalados. Como executo este comando no Windows?
posfan12
(após alguns testes: -1) Ele usa information_schema.user, e nem sempre é legível para todos os usuários
bato3
17

Usei essas ideias para remover a cláusula DEFINER de minha própria saída do mysqldump, mas optei por uma abordagem mais simples:

Apenas remova o !antes do código e o DEFINER, e o resto do comentário se torna um comentário normal.

Exemplo:

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

fica desamparado, tão pouco quanto fazer isso ..

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

A regexp mais fácil, porém, é remover o! e os números

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

Isso remove !#### DEFINERe substitui o DEFINER ... você também poderia remover o DEFINER, realmente não importa - uma vez que o "!" se foi

SitesBySequoia.com
fonte
16

De acordo com as recomendações do outro, aqui está um exemplo de como remover o DEFINER do dump, após o término do dump:

mysqldump -u user --password='password' -h localhost database | grep -v "50013 DEFINER" > dump.sql
Jonathan
fonte
4
Para gatilhos, as linhas se parecem com / *! 50003 CREATE * / / *! 50017 DEFINER = user@ localhost* / / *! 50003 gatilho my_triggername ANTES DE INSERIR EM my_table PARA CADA LINHA .... * / ;; e grep -veliminará totalmente essas linhas. (embora 50017! = 50013)
Kenney
13

Como outros mencionaram, remover o definidor com qualquer tipo de expressão regular não é muito complexo. Mas os outros exemplos eliminaram as definições de exibição para mim.

Esta é a expressão regular que funcionou para mim:

sed -e 's/DEFINER=[^ ]* / /'
Lajos Veres
fonte
E mais rápido ^^ Obrigado
Kevin Labécot,
1
Não funciona com gatilhos - remove também o */. MySQL 5.6.31.
Franc Drobnič
10

Para uma solução automatizada, você pode olhar mysqlmigrate. É um wrapper Bash mysqldumpque permite a você migrar bancos de dados e ignorar as instruções DEFINER. Exemplo:

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

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

Caso contrário, sim, um comando como Abhay aponta é necessário:

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

Outra opção no OSX para remover definidores no arquivo:

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

Você deve procurar a resposta aqui: /dba/9249/how-do-i-change-the-definer-of-a-view-in-mysql/29079#29079

A melhor maneira, em minha opinião, de resolver este problema, é não adicionar uma análise extra de string com sed ou grep ou qualquer outro, em vez disso, o mysqldump é capaz de gerar um bom dump adicionando - single-transaction

Jose Nobile
fonte
Por que votou negativamente? Por que essa resposta não é considerada útil?
Jose Nobile,
1
Sua resposta ainda precisa de cerca de 90 votos positivos para obter a posição que merece. Você tem o meu :)
Patrick van Bergen
4

Uma maneira rápida de fazer isso é canalizar a saída do mysqldump por meio do sed para remover as DEFINERinstruções contidas em comentários condicionais. Eu uso isso para remover DEFINERa partir de CREATE TRIGGERdeclarações, mas você pode ajustar o número da versão condição comentário na regex para atender às suas finalidades.

mysqldump -u user --password='password' -h localhost database | \
  sed 's/\/\*!50017 DEFINER=`.*`@`.*`\*\///' 
Paul Dixon
fonte
1
Uma declaração sed um pouco mais legível: sed "s / DEFINER (. *?) FUNCTION / FUNCTION /"
reustmd
4

Não tenho certeza se ajuda, mas eu uso o SQLyog Community Edition, disponível em: -

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

Ao despejar sql ou copiar para outro banco de dados, ele permite que você 'Ignore o DEFINER'

É gratuito e fornece a funcionalidade básica que muitas pessoas precisam

Também existe uma versão paga disponível em: -

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

Felicidades

itfidds
fonte
Em vez de apenas sinalizar como "não útil", talvez seja mais útil se você responder por que acha que não é útil?
itfidds
3

Para mim, isso funciona: perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp. Isso removeu DEFINER = root @ localhost do meu dump, em cada instrução de procedimento de criação

Rafwell
fonte
2

Aqui está uma solução de trabalho completa para remover informações do DEFINER para MySQL 5.6.xe Linux. (Testado emCentOS 6.5 ).

Normalmente, temos que substituir as seguintes entradas de despejo do Mysql (se tomadas junto com dados e gatilhos / rotinas / funções).

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

O dump foi feito com o comando mysqldump abaixo.

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

O arquivo de despejo necessário sem informações do DEFINER pode ser obtido com os três comandos abaixo.

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 o arquivo de despejo estiver na pasta atual, ignore [PATH /].

Se os dados nas tabelas forem muito grandes, faça o despejo em dois arquivos, em um arquivo despeje o despejo com os dados e em outro arquivo de despejo apenas faça o despejo dos scripts (acionadores / funções / procedimentos.) E execute os três acima comandos no segundo arquivo de despejo (scripts).

I Bajwa PHD
fonte
1

Substitua todos os seus usuários definidores por CURRENT_USER. No meu script Gradle que cria o backup, meu script de substituição se parece com:

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

que realmente é apenas chamar ANT. Então você não terá que se preocupar com isso.

Ryan Shillington
fonte
1

Em máquinas Linux, você pode usar este one-liner:

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

Você só precisa substituir as cadeias de caracteres em negrito pelas credenciais do usuário do banco de dados e nome / padrão do banco de dados.

Mais informações aqui: http://blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/

Novoj
fonte
1

A única maneira de fazê-lo funcionar no Windows:

Instale http://gnuwin32.sourceforge.net/ para ter sed na linha de comando e adicione-o ao PATH do 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
Artur Kędzior
fonte
1

Obrigado a todos pelas dicas. Por ser preguiçoso, escrevi um script chamado: "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
fonte
1

Para algo como:

DELIMITER ;;
CREATE DEFINER = `mydb` @` localhost` FUNCTION `myfunction` () RETURNS int (11)
início
(...)
fim ;;

Experimente isto:

mysqldump --force --routines --opt --user = myuser --databases mydb | sed -e 's / DEFINER = `. *` @ `. *` \ // g'
impactaweb
fonte
1
  1. abra seu banco de dados com qualquer editor, usei com o notepad ++,

  2. encontre todos os testes DEFINER=root@localhost e substitua por nothing ( "") IE. delete isso.

Em seguida, você pode importá-lo para qualquer host que desejar.

Lê Công Danh
fonte
0

O regex mais simples que funciona para mim com todos os objetos é:

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

Observe que quote-namestem que ser TRUE(o que é por padrão).

Espero que nas versões mais recentes a opção --skip-definerintroduzida no mysqlpump na versão 5.7 chegue ao mysqldump também.

Franc Drobnič
fonte
0

Usei o script do PowerShell para remover todas as linhas com DEFINER:

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

Alen
fonte
0

Nada estava funcionando para mim, então precisei escrever minha própria regex.

  1. Tente despejar seu banco de dados em um arquivo, catum arquivo inteiro e grepapenas suas declarações definidoras para vê-los.

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

  2. Escreva sua regex

  3. Canalize seu dump em sed com este regex. Por exemplo, a minha declaração é:

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

  4. Lucro!

Xdg
fonte
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
fonte