我想阻止我的 Amazon Relational Database Service (Amazon RDS) for PostgreSQL 或 Amazon Aurora (Aurora) PostgreSQL 兼容版实例中进行数据定义语言 (DDL) 操作。在使用逻辑复制进行蓝绿部署期间,DDL 操作会导致错误。
简短描述
在使用逻辑复制进行蓝绿部署期间,当 Amazon RDS for PostgreSQL 实例上运行 DDL 操作时,您会收到以下错误消息:
“Data definition language (DDL) changes aren't supported...Your green databases now have a status of REPLICATION_DEGRADED.Delete and recreate your blue/green deployment and avoid future DDL changes...”
当您尝试切换时,Amazon RDS 会阻止切换,且您会收到以下错误消息:
“Switchover from DB cluster to... was cancelled because there are DDL or Large Object changes on... that can't be replicated.Delete the blue/green deployment along with the target cluster, then re-create it.”
在基于 RDS for PostgreSQL 的蓝绿部署中,DDL 操作可能会导致环境之间的逻辑复制性能降级,且需要进行完整的重新部署。为防止此问题,您必须在蓝绿部署期间在蓝色数据库上配置 PostgreSQL 事件触发器和触发器函数。
但是,您无法阻止以下 DDL 操作:
- 针对共享对象(例如数据库、角色或表空间)的命令
- 针对事件触发器的命令
- pg_largeobject 中的大对象修改
**注意:**此问题仅在主要版本升级期间影响 RDS for PostgreSQL,此时 Amazon RDS 使用逻辑复制而非物理复制。原生 PostgreSQL 逻辑复制存在限制,这会在逻辑复制期间阻碍 PostgreSQL 蓝绿部署。有关详细信息,请参阅 PostgreSQL 网站上的 Restrictions(限制)。
解决方法
配置 PostgreSQL 事件触发器和触发器函数
在配置蓝绿部署之前,请创建事件触发器和触发器函数。此外,您必须在每个需要 DDL 保护的数据库中分别创建事件触发器和触发器函数,因为事件触发器在数据库级别运行。默认情况下,绿色环境会继承事件触发器和触发器函数。要在绿色环境中执行 DDL 操作,请先删除您在蓝色环境中创建的触发器和函数。
要配置事件触发器和触发器函数,请完成以下步骤:
-
运行以下命令,以超级用户身份登录数据库:
psql -U admin -h your_rds_endpoint -d your_database
-
运行以下命令创建 DDL 阻止函数:
CREATE OR REPLACE FUNCTION schema_name.block_ddl_bg() RETURNS event_trigger
SECURITY DEFINER
AS $$
DECLARE
-- Define allowed users and roles here
allowed_users TEXT[] := ARRAY['rdsadmin', 'rdsrepladmin'];
allowed_roles TEXT[] := ARRAY['rdsrepladmin'];
BEGIN
-- Check if either the session user or current role is allowed
IF NOT (session_user = ANY(allowed_users) OR current_role = ANY(allowed_roles)) THEN
RAISE EXCEPTION 'DDL operations are blocked to prevent Blue Green Deployment replica degradation. User: %, Role: %, Status: BLOCKED',
session_user, current_role;
END IF;
END;
$$ LANGUAGE plpgsql;
**注意:**在上述命令中,请将 schema_name 替换为您的架构。
-
运行以下命令创建事件触发器:
CREATE EVENT TRIGGER block_ddl_trigger
ON ddl_command_start
EXECUTE FUNCTION schema_name.block_ddl_bg();
**注意:**在上述命令中,请将 schema_name 替换为您的架构。
-
运行以下命令以验证触发器实现:
-- Check if the function exists
SELECT proname, pronamespace::regnamespace
FROM pg_proc
WHERE proname = 'block_ddl_bg';
-- Check if the event trigger exists
SELECT evtname, evtevent, evtowner::regrole
FROM pg_event_trigger
WHERE evtname = 'block_ddl_trigger';
-
运行以下命令以测试触发器:
-- Try to create a test table
CREATE TABLE test_table (id int);
-- Should receive blocking message
删除事件触发器和触发器函数
完成蓝绿部署切换或停用蓝绿部署后,请运行以下命令。
移除事件触发器:
-- Remove event trigger
DROP EVENT TRIGGER block_ddl_trigger;
移除触发器函数:
-- Remove trigger function
DROP FUNCTION schema_name.block_ddl_bg();
**注意:**在上述命令中,请将 schema_name 替换为您的架构。
相关信息
PostgreSQL 网站上的 Event triggers(事件触发器)
PostgreSQL 网站上的 Event trigger firing matrix(事件触发器触发矩阵)
Aurora PostgreSQL 蓝绿部署的限制
使用逻辑复制的 RDS for PostgreSQL 蓝绿部署的限制