编程 在 RDS 上跑 pt-osc:ERROR 1419、参数组重启与 --recursion-method 假死

2026-10-20 00:06:37

在 RDS 上跑 pt-osc:ERROR 1419、参数组重启与 --recursion-method 假死

在 Amazon RDS / Aurora 上执行 pt-online-schema-change,失败点基本集中在权限模型和工具默认行为上,而不是 DDL 本身。按实际踩到的顺序,依次是:建触发器被 ERROR 1419 挡住、PROCESS 权限缺失、--recursion-method 自动发现从库导致进程挂死,以及失败后清理时容易搞反的 DROP 顺序。

Percona 的这篇博客是整条线的起点:pt-online-schema-change on Amazon RDS。

1. 第一个失败点:ERROR 1419 / db do failed

RDS 不提供 SUPER 权限。实例一旦开启 binlog,pt-osc 会在创建触发器这一步直接失败,报错原文:

DBD::mysql::db do failed: You do not have the SUPER privilege and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable) [for Statement "CREATE TRIGGER `pt_osc_db_table_del` AFTER DELETE ON `db`.`table` FOR EACH ROW DELETE IGNORE FROM `db`.`_table_new` WHERE `db`.`_table_new`.`table_id`  OLD.`table_id` AND `db`.`_table_new`.`account_id`  OLD.`account_id`"] at /usr/bin/pt-online-schema-change line 10583.

原因:MySQL 在开启 binlog 的服务器上创建触发器或存储函数时,要求执行用户具有 SUPER 权限,本质上是要求用户声明信任这些程序是 deterministic 的。RDS 永远不会给 SUPER,所以唯一的解法是 log_bin_trust_function_creators=1。

对应的 MySQL 原生报错是:

ERROR 1419 (HY000): You don't have the SUPER privilege and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable)

Percona 博客最初写的是 SET GLOBAL log_bin_trust_function_creators = 1;,后来在评论区更正:RDS 上不能用 SET GLOBAL,必须改实例参数组。

2. 在 RDS 上改 log_bin_trust_function_creators

AWS re:Post 的这篇讲得比较完整:。

RDS 是托管服务,不提供系统权限,也没有 SUPERUSER。如果创建实例时没有指定参数组,RDS 会分配一个 default DB parameter group,而默认组不可修改,必须新建 custom 参数组,把 log_bin_trust_function_creators 设为 1;保存后至少等 5 分钟再关联,让新参数组的状态稳定下来。

关联时在 Databases 里选中实例 → Modify → 选新参数组 → Reboot。参数组名会立刻变更,但 RDS 要重启后才应用参数值,这个重启不会触发 failover。

如果实例本来就在使用自己的 custom 参数组,流程短很多:只改值并保存即可。log_bin_trust_function_creators 是 dynamic 参数,不需要重启,改完立刻用下面这条确认:

SHOW VARIABLES LIKE 'log_bin_trust_function_creators';

一个容易忽略的前提:开自动备份就等于开 binlog。很多人以为自己“没开 binlog”,实际上备份策略已经把它打开了。

改完记得改回 0。babbel 那篇文章给的理由是:允许创建标了 DETERMINISTIC 的非确定函数,会让 binlog 内容不可靠,复制到备库或从快照恢复时都可能带错数据,而且这类问题不容易被发现。迁移结束就关回去。

Aurora 同理,只能在参数组里改,集群参数组和实例参数组按实际情况选。论坛帖 18879 里,用户用 admin 账号跑 pt-osc 仍然报 Error creating triggers: ... You do not have the SUPER privilege and binary logging is enabled,结论就是去参数组改。该用户还试过改 my.cnf、/etc/percona-toolkit/pt-online-schema-change.conf、~/.percona-toolkit.conf,全都不起作用;最后一种写法不对时还会报 Unknown option: a ...。

3. 第二个失败点:PROCESS 权限

参数组改完,下一道坎是权限。报错原文(stackoverflow 69442250):

You do not have the PROCESS privilege at /usr/bin/pt-online-schema-change line 4456,  line 1

最小授权清单:

GRANT PROCESS, SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO my_user;
GRANT ALL PRIVILEGES ON `my_db`.* TO my_user;

各权限的用途:PROCESS 是 --recursion-method processlist 用来从 processlist 里找从库的;REPLICATION CLIENT / REPLICATION SLAVE 用于读取从库状态和延迟。RDS 里这些权限可以授予普通用户,不必用 master user。

4. 第三个失败点:--recursion-method 自动发现从库导致假死

权限补齐后,工具可能既不报错也不退出,就停在 --execute 阶段,光标不动,processlist 里偶尔闪过一条 SELECT @@SERVER_ID。这就是 forums.percona.com/t/30542 里的现象。

用 PTDEBUG=1 跑,日志停在:

# MasterSlave:4304 12721 Recursion methods: processlist hosts
# MasterSlave:4350 12721 SELECT @@SERVER_ID

原因是工具默认从 processlist / hosts 自动发现从库,一旦发现到的主机或 IP 不可达,就卡在连接阶段。加 --recursion-method=NONE 可以立刻通过。

论坛回复里 Ivan Groenewold 的解释也是这个:工具会自动发现从库,发现的主机名或 IP 不可达就会挂住。如果想保留基于延迟的限流,就用 DSN 精确指定要监控的从库:

--recursion-method "dsn=D=percona,t=dsns"

dsns 表结构:

CREATE TABLE `dsns` (`id` int(11) NOT NULL AUTO_INCREMENT, `parent_id` int(11) DEFAULT NULL, `dsn` varchar(255) NOT NULL, PRIMARY KEY (`id`));
INSERT INTO dsns (parent_id,dsn) values (1, "h=x.x.x.x,u=repl,p=xx,P=3307");

在 RDS / Aurora 场景下,集群端点和实例端点不是一回事,自动发现拿到的内网地址经常不可达。所以只有两个可选方案:NONE(放弃从库延迟限流),或者用 dsn 把需要监控的从库列清楚。用 NONE 意味着 --max-lag 失效,只剩 --max-load / --critical-load 兜底。

5. CREATE TRIGGER 不是原子的

即使前面都过了,高写入表上仍可能在建触发器时失败(dba.stackexchange 268592):

Error creating triggers: ... DBD::mysql::db do failed: Lock wait timeout exceeded; try restarting transaction [for Statement "CREATE TRIGGER `pt_osc_master_website_del` ..."] at /usr/bin/pt-online-schema-change line 11074

pt-osc 的三个触发器(INSERT / DELETE / UPDATE)是逐个创建的,不是原子操作。高写入表上 CREATE TRIGGER 需要拿 MDL,同样可能等到 lock wait timeout。

失败后清理时,帖子里给的顺序是先 DROP TABLE _website_new 再 DROP TRIGGER,这个顺序有风险:触发器还在、新表已经没了,原表后续写入会报 ERROR 1146 Table 'db._xxx_new' doesn't exist(Launchpad bug 1188002)。正确顺序是先 DROP TRIGGER,再 DROP TABLE。

6. MySQL 8.0.36 起的变化

RDS for MySQL 8.0.36 起,不能直接修改 mysql 库里的表。主管理账号带 rds_superuser_role,该角色包含 ALTER、TRIGGER、PROCESS、REPLICATION CLIENT、REPLICATION SLAVE、SET_USER_ID 等权限,但仍然不是 SUPER。

所以 ERROR 1419 那条路径没有变化:还是改参数组,还是迁移完改回 0。权限模型细节见 AWS 文档。

链接

  • Percona:
  • AWS re:Post:
  • 论坛假死帖:
  • Aurora 1419:
  • 权限报错:
  • CREATE TRIGGER 失败:
  • 8.0.36 权限模型:
  • 参数组风险说明:

推荐文章

程序员茄子在线接单