如何批量更改MySQL触发器DEFINER

时间:2013-09-03 13:35:09

标签: mysql triggers

我一直在研究我们的内部开发服务器并在我们的MySQL 5.6.13服务器上创建MySQL触发器。我现在遇到的问题是在内部服务器上使用DEFINER = root @ %创建了触发器(总共大约200个)。

现在我想转移到实时制作服务器。但是在我们的实时服务器上,我们不允许用户root访问。因此,我如何批量更改所有触发器,以便它读取DEFINER = root @ localhost

8 个答案:

答案 0 :(得分:52)

一种方法:

1)将触发器定义转储到文件

# mysqldump -uroot -p --triggers --add-drop-trigger --no-create-info \
      --no-data --no-create-db --skip-opt test > /tmp/triggers.sql

2)在您喜欢的编辑器中打开triggers.sql文件,然后使用Find and Replace功能更改DEFINER。保存更新的文件。

3)从文件

重新创建触发器
# mysql < triggers.sql

答案 1 :(得分:4)

不使用--add-drop-trigger选项:

currentUserDefiner='root'
currentHostDefiner='localhost'
newUserDefiner='user'
newHostDefiner='localhost'
db='myDb'
mysqldump -u root --triggers --no-create-info --no-data --no-create-db --skip-opt $db \
| perl -0777 -pe 's/(\n\/\*.+?50003 TRIGGER `([^`]+)`)/\nDROP TRIGGER \2;\1/g' \
| perl -0777 -pe 's/(DEFINER[^`]+)'$currentUserDefiner'(`@`)'$currentHostDefiner'/\1'$newUserDefiner'\2'$newHostDefiner'/gi' \
> out.sql
mysql -u root < out.sql

答案 2 :(得分:1)

接受的答案对我不起作用,因为我的大多数客户都托管在5.5的服务器上,而我可以做的不多, --add-drop-trigger function was added in 5.6

在敲了敲我的头后,我刚进入phpMyAdmin,在触发器编辑页面上暴露了定义器,我只是编辑了20个左右触发器的定义器 - phpMyAdmin将丢弃并重新创建触发器新的定义者。

我找到的另一个选项是完成一个完整的mysqldump,编辑生成的文件,用它来创建一个新数据库,然后使用像Navicat这样的工具执行结构同步回原始数据库,只选择所需的触发器。结果比较清单。这对我来说是一个更长的过程,因为我只需要编辑20个触发器,但如果我必须更新数百个触发器,这将更快。

答案 3 :(得分:1)

另一种方法是使用此Java实用程序。请注意,这是一项正在进行的工作,因为当前版本1.0清除了一些服务器变量。 newdef

答案 4 :(得分:1)

我知道这是一篇过时的文章,但也许​​可以对某人有所帮助。

我使用此sql查询生成DROP和CREATE命令:

SELECT CONCAT("DROP TRIGGER ", trigger_name, ";", " CREATE TRIGGER ", TRIGGER_NAME, " AFTER ", EVENT_MANIPULATION, " ON ", EVENT_OBJECT_SCHEMA, ".", EVENT_OBJECT_TABLE, " FOR EACH ROW ", ACTION_STATEMENT, ";") AS sqlCommand FROM information_schema.triggers WHERE EVENT_OBJECT_SCHEMA = "yourdatabase";

当我将生产数据库带到开发机器并在所有命令上使用foreach进行操作并自动重新创建触发器时,我在应用程序中使用了此功能。这给了我自动化的选择。

PHP / Laravel中的示例:

    $this->info('DROP and CREATE TRIGGERS');
    $pdo = DB::connection()->getPdo();
    $sql = 'SELECT CONCAT("DROP TRIGGER ", trigger_name, ";", " CREATE TRIGGER ", TRIGGER_NAME, " AFTER ", EVENT_MANIPULATION, " ON ", EVENT_OBJECT_SCHEMA, ".", EVENT_OBJECT_TABLE, " FOR EACH ROW ", ACTION_STATEMENT, ";") AS sqlCommand FROM information_schema.triggers WHERE EVENT_OBJECT_SCHEMA = "mydatabase";';
    $stmt = $pdo->prepare($sql, [PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true]);
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $stmt->closeCursor();

    foreach($result as $rs){
        $pdo = DB::unprepared($rs['sqlCommand']);
        break;
    }

提示:由于mysql缓冲区查询问题,我必须使用pdo进行操作,here

我的观点也一样(在这里您可以使用ALTER TABLE):

    $pdo = DB::connection()->getPdo();
    $sql = 'SELECT CONCAT("ALTER DEFINER=`homestead` VIEW ", table_name," AS ", view_definition,";") AS sqlCommand FROM  information_schema.views WHERE table_schema="mydatabase";';
    $stmt = $pdo->prepare($sql, [PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true]);
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $stmt->closeCursor();
    $this->info('View definer changed');

    foreach($result as $rs){
        $pdo = DB::unprepared($rs['sqlCommand']);
    }

希望有帮助。

答案 5 :(得分:1)

运行此sql语句(用所需的触发器替换表名和触发器名):

$ mysql -V
mysql  Ver 15.1 Distrib 5.5.64-MariaDB, for Linux (x86_64) using readline 5.1

然后修改结果并执行。

答案 6 :(得分:0)

使用MySQL Workbench中的选项主题的另一个变体是使用“mysqldump”转储整个数据库,在功能强大的编辑器中打开转储,找到替换为所需的“DEFINER”,然后使用MyQSL Workbench导入“转储”在导入屏幕上选择了结构选项“(v6.2)。

答案 7 :(得分:0)

我能够通过关闭MySQL服务器来更新触发器定义程序,然后更新表.TRG文件(这些文件是文本文件,在其中查找定义程序和CREATE DEFINER),然后重新启动MySQL。我只需要为一张桌子做,但是如果有很多桌子,我会按照这些原则编写一个sed脚本或其他东西。如果服务器无法关闭,则以下各项应能非常顺利地进行,而对活动的干扰很小(免责声明-我尚未对其进行测试):

每个表:

  • 锁定表t写
  • 冲洗桌子t
  • 对TRG文件执行sed魔术
  • 解锁表t