我一直在我们的内部开发服务器上工作,并在我们的 MySQL 5.6.13 服务器上创建 MySQL 触发器。我现在遇到的问题是触发器(总共大约 200 个)是在内部服务器上使用 DEFINER= root
@创建的。%
现在我想转移到现场生产服务器。但是,在我们的实时服务器上,我们不允许用户 root 进行此访问。因此,我怎样才能批量更改我的所有触发器,以便它读取 DEFINER= root
@localhost
一种方法:
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
s. 保存更新的文件。
3) 从文件重新创建触发器
# mysql < triggers.sql
不使用 --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
我知道这是一个旧帖子,但也许它可以帮助某人。
我使用这个 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']);
}
希望能帮助到你。
运行此 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';
然后修改结果并执行。
接受的答案对我不起作用,因为我的大多数客户端都托管在 5.5 的服务器上,对此我无能为力,并且在 5.6 中添加了 --add-drop-trigger 功能
在对此进行了猛烈抨击之后,我只是进入了 phpMyAdmin,它在触发器编辑页面上公开了定义器,我只是为大约 20 个错误的触发器编辑了定义器 - phpMyAdmin 将删除并使用新的定义器重新创建触发器.
我发现的另一个选择是做一个完整的 mysqldump,编辑生成的文件,用它来创建一个新的数据库,然后使用像 Navicat 这样的工具执行结构同步回原始数据库,在结果比较列表中只选择所需的触发器. 这对我来说是一个更长的过程,因为我只需要编辑 20 个触发器,但如果我必须更新数百个触发器,这会更快。
在 MySQL Workbench 中使用选项的另一个主题变体是使用“mysqldump”转储整个数据库,在功能强大的编辑器中打开转储,找到替换为所需的“DEFINER”,然后使用 MyQSL Workbench 导入“Dump Structure Option” (v6.2) 在导入屏幕上选择。
另一种方法是使用这个 Java 实用程序。请注意,这是一项正在进行的工作,因为当前版本 1.0 清除了一些服务器变量。 新定义
我可以通过关闭 MySQL 服务器来更新触发器定义器,然后更新表 .TRG 文件(这些是文本文件,在其中查找定义器和 CREATE DEFINER),然后重新启动 MySQL。我只需要为一张桌子做这件事,但如果有很多,我会写一个 sed 脚本或类似的东西。如果服务器无法关闭,则以下内容应该非常顺利,对活动的干扰很小(免责声明 - 我没有测试过):
对于每个表: