如何批量更改MySQL触发器定义器
我一直在开发我们的内部开发服务器,并在MySQL 5.6.13服务器上创建MySQL触发器。我现在的问题是触发器(总共大约200个)是在内部服务器上使用as DEFINER=如何批量更改MySQL触发器定义器,mysql,triggers,Mysql,Triggers,我一直在开发我们的内部开发服务器,并在MySQL 5.6.13服务器上创建MySQL触发器。我现在的问题是触发器(总共大约200个)是在内部服务器上使用as DEFINER=root@%创建的 现在我想转到实时生产服务器。但是,在我们的实时服务器上,我们不允许root用户进行此访问。因此,如何批量更改所有触发器,使其读取DEFINER=root@localhost一种方法: 1) 将触发器定义转储到文件中 #mysqldump-uroot-p--triggers--add drop trigge
root
@%
创建的
现在我想转到实时生产服务器。但是,在我们的实时服务器上,我们不允许root用户进行此访问。因此,如何批量更改所有触发器,使其读取DEFINER=root
@localhost
一种方法:
1) 将触发器定义转储到文件中
#mysqldump-uroot-p--triggers--add drop trigger--no create info\
--无数据--无创建数据库--跳过opt test>/tmp/triggers.sql
2) 在您喜爱的编辑器中打开triggers.sql
文件,并使用Find and Replace
功能更改DEFINER
s。保存更新的文件
3) 从文件中重新创建触发器
#mysql
接受的答案对我不起作用,因为我的大多数客户机都托管在5.5版本的服务器上,对此我无能为力,而
在我的头撞上这个之后,我刚刚进入phpMyAdmin,它在触发器编辑页面上公开了定义者,我只是为20个左右错误的触发器编辑了定义者-phpMyAdmin将删除并用新的定义者重新创建触发器
我发现的另一个选项是执行一个完整的mysqldump,编辑生成的文件,使用它创建一个新的数据库,然后使用像Navicat这样的工具执行结构同步,返回到原始数据库,在生成的比较列表中只选择所需的触发器。这对我来说是一个更长的过程,因为我只需要编辑20个触发器,但如果我必须更新数百个触发器,这将更快。不使用--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
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的/(\n\/\*.+?50003触发器`([^`]+)`)/\nDROP触发器\2\1/g'\
|perl-0777-pe的/(定义者[^`]+)'$currentUserDefiner'(`@`)'$currentHostDefiner'/\1'$newUserDefiner'\2'$newHostDefiner'/gi'\
>out.sql
mysql-u root
另一种方法是使用此Java实用程序。注意,这是一项正在进行的工作,因为当前版本1.0清除了一些服务器变量。
主题的另一个变体是使用MySQL Workbench中的选项转储整个数据库,在一个功能强大的编辑器中打开转储,找到替换为所需的“定义者”,然后使用MyQSL Workbench导入,导入屏幕上选择的“转储结构选项”(v6.2)。我知道这是一篇老文章,但也许它能帮助一些人 我使用此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;
}
提示:我必须使用pdo,因为mysql缓冲区查询问题,如前所述
与我对视图所做的相同(这里您可以使用ALTER TABLE):
希望有帮助。运行此sql语句(用所需触发器替换tablename和triggername):
选择CONCAT('DROP TRIGGER IF EXISTS`',TRIGGER_name',`;',CHAR(13),'DELIMITER$$',CHAR(13),'CREATE TRIGGER`',TRIGGER_name',`',ACTION_timening',EVENT_MANIPULATION',ON',EVENT_OBJECT_SCHEMA',EVENT_OBJECT TABLE',FOR EACH ROW',ACTION_语句,$$,CHAR DELIMITER(13),'DELIMITER;')作为命令
来自信息\u schema.triggers
其中EVENT\u OBJECT\u SCHEMA='tablename'
触发器名称='triggername';
然后修改结果并执行它。我可以通过关闭MySQL服务器更新触发器定义器,然后更新table.TRG文件(这些是文本文件,在其中查找定义器并创建定义器),然后重新启动MySQL来更新触发器定义器。我只需要为一个表执行此操作,但如果有很多表,我会编写一个sed脚本或类似的脚本。如果服务器无法关闭,则以下操作应能非常顺利地工作,对活动的干扰很小(免责声明-我没有对其进行测试): 对于每个表:
- 锁表t写
- 冲洗台t
- 在TRG文件上执行sed魔术
- 解锁表t
sed-e的/DEFINER[]*=[]*[^*]*\*/\*/'
我必须删除--跳过opt
,才能工作。如果有人偶然发现了这一点。但这是一个非常有用的答案,在2021年仍然有效。您当然可以编辑转储创建的文件,并添加“drop trigger if exists name of triger;”是的,但那需要更多的打字。如果我没有一个好的数据库比较工具,那将是如何做到这一点。否则很好。这里的讨论推迟了几年,但我会将查询改为:SELECT CONCAT(“DROP TRIGGER”,TRIGGER_name,”;“,“CREATE TRIGGER”,TRIGGER_name,”,ACTION_TIMING,”,EVENT_操纵,“ON”,EVENT_OBJECT_SCHEMA,”,EVENT_OBJECT_TABLE,“FOR EACH ROW”,ACTION_STATEMENT,“;”)作为来自information_schema.triggers的sqlCommand,其中EVENT_OBJECT_schema=“yourdatabase”代码>这允许“BEFORE”触发器工作。实际上它不是tablename,而是dbname。
$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']);
}