从MySQL转储中删除DEFINER子句


114

我有一个数据库的MySQL转储。其中包含DEFINER子句,

"DEFINER=`root`@`localhost`" 

即,这些DEFINER子句位于我的CREATE VIEW和CREATE PROCEDURE语句中。有没有办法从我的转储文件中删除这些DEFINER子句?


几年前报告了一个错误,但它似乎已被放弃:bugs.mysql.com/bug.php?id=24680
1234ru

Answers:


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,请删除整个字符串。
阿贝(Abhay)2012年

3
我建议提一下,可以像这样将其设置为CURRENT_USER而不是删除DEFINER:sed -E 's/DEFINER=[^ ]+@ [^] + /DEFINER=CURRENT_USER/g' dump.sql > new_dump.sql它具有保留限制/访问控制的优点。
4thfloorstudios,2016年

27
sed命令不会从过程和函数中删除DEFINER子句。这是处理视图,触发器,过程和功能的增强版本: sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*PROCEDURE/PROCEDURE/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*FUNCTION/FUNCTION/'
Vladimir Strugatsky

4
仅供参考---尽管在回答此问题时情况并非如此,但MySQL> 5.6现在附带了一个支持“ --skip-definer”的mysqldump(1)选项:dev.mysql.com/doc/refman /5.7/en/...
Kevin_Kinsey

4
不,这不是mysqldump的,但MySQL的p UMP谁拥有--skip-定义者。
Xdg

70

您可以使用SED删除

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

在MacOS中:

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

MacOS在这里发生了什么变化?
亚历克斯

1
在Mac上sed的联机帮助页上说: -i extension“就地编辑文件,以指定的扩展名保存备份。如果给出了零长度的扩展名,则不会保存任何备份。建议在以下情况下不提供零长度的扩展名:就地编辑文件,因为在磁盘空间用尽等情况下,您可能会遭受损坏或部分内容的风险。”
乍得

很高兴知道,@ Chad。我在Mac中使用sed已有5年以上了。我从来没有空间或损坏的文件的问题。但是,当然是要考虑的事情。感谢您的澄清。
里卡多·马丁斯

我也从未在Mac上遇到过这些问题。自从@Alex问起我就想澄清
乍得

57

从mysql 5.7.8版本开始,您可以在--skip-definermysqlpump中使用该选项,例如:

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

请参阅http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html#option_mysqlpump_skip-definer上更新的mysql手册


8
谁想知道mysqldump和之间的区别是什么mysqlpump-这里是相关的问题:dba.stackexchange.com/questions/118846/mysqldump-vs-mysqlpump
Scadge

我安装了phpMyAdmin和MySQL Workbench。如何在Windows上执行此命令?
posfan12

(经过一些测试:-1)它使用information_schema.user,并且并非始终对所有用户可读
bato3

17

我使用这些想法从我自己的mysqldump输出中剥离了DEFINER子句,但是我采用了一种更简单的方法:

只需删除 !代码和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=[^ ]* / /'

更快^^谢谢
KevinLabécot15年

1
不适用于触发器-还会删除*/。MySQL 5.6.31。
FrancDrobnič'16 -10-26

10

对于自动化解决方案,您可以查看mysqlmigrate。它是一个Bash包装器mysqldump,可让您迁移数据库并忽略DEFINER语句。例:

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

http://thesimplesynthesis.com/post/mysqlmigrate(或GitHub

否则,是的,需要一个类似Abhay的命令:

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

6

OSX上另一个在文件中删除定义程序的选项:

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

5

您应该在这里查看答案:https : //dba.stackexchange.com/questions/9249/how-do-i-change-the-definer-of-a-view-in-mysql/29079#29079

我认为解决此问题的最佳方法是,不使用sed或grep或其他任何方法添加额外的字符串解析,而mysqldump可以通过添加--single-transaction来生成良好的转储


为什么投票?为什么这个答案没有用?
Jose Nobile

1
您的回应仍然需要大约90票赞成票才能获得应有的地位。你有我的:)
Patrick van Bergen

4

一种快速的方法是通过sedmysqldump的输出通过管道传递出去,以删除DEFINER条件注释中包含的语句。我使用它DEFINERCREATE TRIGGER语句中删除,但是您可以调整正则表达式中的条件注释版本号以适合您的目的。

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

1
sed语句更具可读性:sed“ s / DEFINER(。*?)FUNCTION / FUNCTION /”
reustmd 2013年


3

对我来说,这个工程:perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp。在每个创建过程语句中,这从我的转储中删除了DEFINER = root @ localhost


2

这是删除MySQL 5.6.xLinux和Linux的DEFINER信息的完整工作解决方案CentOS 6.5

通常,我们必须替换Mysql dump中的以下条目(如果与数据和触发器/例程/函数一起使用)。

/*!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 /]。

如果表中的数据非常大,则将转储分为两个文件,在一个转储文件中进行包含数据的转储,而在其他转储文件中进行仅脚本的转储(触发器/函数/过程),然后运行以上三个第二个转储(脚本)文件上的命令。


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

您只需用数据库用户凭据和数据库名称/类似模式替换粗体字串。

此处提供更多信息:http : //blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/


1

我可以在Windows下运行的唯一方法:

安装http://gnuwin32.sourceforge.net/以在命令行中sed并将其添加到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

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`函数`myfunction`()返回int(11)
开始
(...)
结束 ;;

试试这个:

mysqldump –force –例程–opt –user = myuser –数据库 sed -e's / DEFINER =`。*`@`。*`\ // g'

1
  1. 使用任何与notepad ++一起使用的编辑器打开您的数据库,

  2. 找到所有测试,DEFINER=root@localhost 并将其替换为nothing("")IE。删除它。

然后,您可以将其导入到所需的任何主机。


0

适用于所有对象的最简单的正则表达式是:

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

请注意,quote-names必须TRUE(默认情况下)。

希望在较新的版本中,--skip-definer在5.7版的mysqlpump中引入的开关也可以在mysqldump中使用。


0

我已经使用PowerShell脚本删除了以下所有行DEFINER

获取内容$ file_in_full_path | 选择字符串模式$ 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.