21

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

现在我想转移到现场生产服务器。但是,在我们的实时服务器上,我们不允许用户 root 进行此访问。因此,我怎样才能批量更改我的所有触发器,以便它读取 DEFINER= root@localhost

4

8 回答 8

65

一种方法:

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功能更改DEFINERs. 保存更新的文件。

3) 从文件重新创建触发器

# mysql < triggers.sql
于 2013-09-03T15:47:17.310 回答
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
于 2015-03-12T10:22:00.790 回答
3

我知道这是一个旧帖子,但也许它可以帮助某人。

我使用这个 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 执行此操作,在此处描述

我对我的观点也这样做(在这里你可以使用 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']);
    }

希望能帮助到你。

于 2018-06-20T07:53:40.233 回答
2

运行此 sql 语句(将 tablename 和 triggername 替换为所需的触发器):

SELECT CONCAT('DROP TRIGGER IF EXISTS `', trigger_name, '`;', CHAR(13), 'DELIMITER $$', CHAR(13), 'CREATE TRIGGER `', TRIGGER_NAME, '` ', ACTION_TIMING, ' ', EVENT_MANIPULATION, ' ON ', EVENT_OBJECT_SCHEMA, '.', EVENT_OBJECT_TABLE, ' FOR EACH ROW ', ACTION_STATEMENT, '$$', CHAR(13), 'DELIMITER ;') AS command
FROM information_schema.triggers
WHERE EVENT_OBJECT_SCHEMA = 'tablename'
AND TRIGGER_NAME = 'triggername';

然后修改结果并执行。

于 2020-02-04T11:14:31.167 回答
1

接受的答案对我不起作用,因为我的大多数客户端都托管在 5.5 的服务器上,对此我无能为力,并且在 5.6 中添加了 --add-drop-trigger 功能

在对此进行了猛烈抨击之后,我只是进入了 phpMyAdmin,它在触发器编辑页面上公开了定义器,我只是为大约 20 个错误的触发器编辑了定义器 - phpMyAdmin 将删除并使用新的定义器重新创建触发器.

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

于 2014-08-23T21:51:22.007 回答
1

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

于 2017-02-19T02:19:15.983 回答
1

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

于 2016-05-01T15:30:36.540 回答
0

我可以通过关闭 MySQL 服务器来更新触发器定义器,然后更新表 .TRG 文件(这些是文本文件,在其中查找定义器和 CREATE DEFINER),然后重新启动 MySQL。我只需要为一张桌子做这件事,但如果有很多,我会写一个 sed 脚本或类似的东西。如果服务器无法关闭,则以下内容应该非常顺利,对活动的干扰很小(免责声明 - 我没有测试过):

对于每个表:

  • 锁定表 t 写入
  • 冲洗表 t
  • 对 TRG 文件执行 sed 魔术
  • 解锁表
于 2020-03-17T02:20:16.120 回答