从MySQL Dumps中删除DEFINER子句

时间:2012-02-25 18:28:51

标签: mysql

我有一个我的数据库的MySQL转储。其中有DEFINER条款,看起来像,

"DEFINER=`root`@`localhost`" 

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

28 个答案:

答案 0 :(得分:90)

我认为没有办法忽略将DEFINER添加到转储中。但是有一些方法可以在创建转储文件后删除它们。

  1. 在文本编辑器中打开转储文件,并将所有出现的DEFINER=root@localhost替换为空字符串“”

  2. Edit the dump (or pipe the output) using perl:

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

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

答案 1 :(得分:55)

您可以使用SED删除

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

在MacOS中:

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

答案 2 :(得分:39)

从mysql 5.7.8版开始,你可以在mysqlpump上使用--skip-definer选项,例如:

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手册

答案 3 :(得分:17)

根据其他人的建议,以下是转储完成后如何从转储中删除DEFINER的示例:

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

答案 4 :(得分:14)

我使用这些想法从我自己的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,它并不重要 - 一旦"!"已经不见了

答案 5 :(得分:13)

正如其他人所说,用任何一种正则表达方式剥离定义者都不是太复杂。 但其他例子剥夺了我的视图定义。

这是对我有用的正则表达式:

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

答案 6 :(得分:9)

对于自动化解决方案,您可以查看mysqlmigrate。它是mysqldump周围的Bash包装器,它允许您迁移数据库并忽略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

答案 7 :(得分:4)

快速执行此操作的方法是将mysqldump的输出通过sed来管道,以删除条件注释中包含的DEFINER语句。我使用它来从DEFINER语句中删除CREATE TRIGGER,但您可以在正则表达式中调整条件注释版本号以适合您的目的。

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

答案 8 :(得分:4)

不确定是否有帮助,但我使用的是SQLyog社区版,可从以下网址获取:

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

当转储sql或复制到另一个数据库时,它允许你“忽略DEFINER'

它是免费的,并提供许多人需要的基本功能

还提供付费版本: -

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

干杯

答案 9 :(得分:4)

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

我认为解决这个问题的最好方法是不添加额外的sed或grep或其他任何字符串解析,而是mysqldump能够通过添加--single-transaction

来生成一个好的转储。

答案 10 :(得分:4)

OSX上另一个删除文件内定义符的选项:

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

答案 11 :(得分:3)

对我而言,这有效:perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp。 这在每个创建过程语句

中从我的转储中删除了DEFINER = root @ localhost

答案 12 :(得分:2)

这是一个完整的工作解决方案,可以删除MySQL 5.6.x和Linux的DEFINER信息。(在CentOS 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 /].

如果表中的数据非常庞大,则将转储分为两个文件,在一个转储文件中,使用带有数据的转储和其他转储文件中的转储仅使用脚本转储(触发器/函数/过程。)并运行第二个转储(脚本)文件中的上述三个命令。

答案 13 :(得分:1)

用CURRENT_USER替换所有定义者用户。在我创建备份的gradle脚本中,我的替换脚本如下所示:

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

这真的只是叫ANT。那你就不用担心了。

答案 14 :(得分:1)

没有问题的最佳转储和还原方式:

MYSQL DUMP

mysqldump -h HOST -u USER -pPASSWORD --single-transaction --quick --skip-lock-tables --triggers --routines --events DATABASE | gzip > "DATABASE.sql.gz" &

MYSQL恢复

gunzip DATABASE.sql.gz

sed -i 's/DEFINER=[^ ]* / /' DATABASE.sql
sed -i 's/SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;/ /' DATABASE.sql
sed -i 's/SET @@SESSION.SQL_LOG_BIN= 0;/ /' DATABASE.sql
sed -i 's/SET @@GLOBAL.GTID_PURGED='';/ /' DATABASE.sql
sed -i 's/SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN;/ /' DATABASE.sql

mysql -h HOST -u USER -pPASSWORD < DATABASE.sql

答案 15 :(得分:1)

类似于:

DELIMITER ;;
CREATE DEFINER=`mydb`@`localhost` FUNCTION `myfunction`() RETURNS int(11)
begin
(...)
end ;;

试试这个:

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

答案 16 :(得分: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

答案 17 :(得分: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

答案 18 :(得分: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/

答案 19 :(得分:0)

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

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

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

希望在较新的版本中,版本5.7中的mysqlpump中引入的开关--skip-definer也会出现在mysqldump中。

答案 20 :(得分:0)

我使用PowerShell脚本删除了DEFINER的所有行:

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

答案 21 :(得分:0)

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

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

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

答案 22 :(得分:0)

什么都没有为我工作,所以我需要编写自己的正则表达式。

  1. 尝试将数据库转储到文件,cat整个文件和grep仅转储到定义程序语句中以查看它们。

    cat 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. 利润!

答案 23 :(得分: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

答案 24 :(得分:0)

请参阅https://stackoverflow.com/a/19707173/1488762,我怀疑以下内容在超大型数据库上可能会更好-在最后修改定义器,而不是在每一行上执行其他正则表达式处理:

mysqldump myDB > dump.sql
cat >> dump.sql << END
SELECT CONCAT("ALTER DEFINER=`youruser`@`host` VIEW ", 
table_name, " AS ", view_definition, ";") 
FROM information_schema.views 
WHERE table_schema='myDB';
END

答案 25 :(得分:0)

仅供我将来参考,sd版本。

mysqldump ... | sd 'DEFINER=.*?\*' '*' > file.sql

答案 26 :(得分:0)

我在 MariaDB 10.3 上测试的删除 DEFINER 的解决方案:

mysqldump | grep -v -P 'SQL SECURITY DEFINER \*/$' | perl -pe 's/(?<=^\/\*!50003 CREATE\*\/ )\/\*!50017 DEFINER=`.+`@`.+`\*\/ (?=\/\*!50003 TRIGGER)//'

grep 为视图删除它,perl 为触发器删除它

这个解决方案是防攻击的,因为它匹配行的开头和结尾。因此,即使攻击者知道您正在替换转储中的 DEFINER,他在数据中排列的 DEFINER 也不会被替换。

答案 27 :(得分:0)

如果您的 SQL 文件有 DEFINER 次出现(有和)没有条件注释,那么您可能对这个替代的 REGEXP 感兴趣。

sed -Ei \
    's/DEFINER\s*=\s*(["'\''`]?)[^"'\''`@]+\1\s*@\s*(["'\''`]?)[^"'\''`\*]+\2//g' \
#      [-----1------][----2----][----4----]-5[--6--][----------7------------]
    "$FILE"

说明:

  1. DEFINER {potential whitespace} = {potential whitespace} ...
  2. ... {任何潜在的引用或反引号,捕获} ...
  3. (中断序列,添加转义单引号,恢复序列——因为我们用单引号包裹了结构)
  4. ... (username) {string: no quote or @} ...
  5. … {使用第一个捕获组 – 引用 – 如果有的话} …
  6. ... {潜在空白} @ {潜在空白} ...
  7. ... {对于具有新捕获组的主机相同,但也排除星号}。

(在没有注释的解释行的情况下运行,因为这会引发错误)