使用 Exec_node() 和 Spock OSS 简化全集群 PostgreSQL 执行
Simplifying Cluster-Wide PostgreSQL Execution with Exec_node() and Spock OSS

原始链接: https://www.pgedge.com/blog/simplifying-cluster-wide-sql-execution-in-pgedge-with-exec_node

## pgEdge 的 `exec_node()`:简化的分布式数据库管理 pgEdge 是一个分布式 Postgres 系统,专为全球、多主部署而设计。管理这些集群需要执行命令——例如 DDL 语句或管理任务——在*特定*节点上,而标准的复制并不总是能处理这些。为此,创建了 `exec_node()` 函数。 `exec_node()` 允许用户从数据库内部远程执行 SQL 命令,目标可以是单个节点或整个集群。它特别适用于那些设计上不进行复制的操作,例如创建数据库、更改系统设置或管理 Spock(pgEdge 的逻辑复制扩展)。 该函数简化了以前需要手动登录或编写脚本的任务,提供了一种更安全、更可审计且易于自动化的解决方案。示例包括在特定节点上运行维护 (`SELECT exec_node('VACUUM ANALYZE;', 'node1');`) 或在所有节点上设置 GUC 值。 `exec_node()` 无缝集成到现有工作流程中,减少错误并简化 pgEdge 用户的集群管理。它在 GitHub 上可用 ([https://github.com/pgEdge/](https://github.com/pgEdge/)),并显著提高了运营效率。

黑客新闻 新 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 简化全集群PostgreSQL执行,使用Exec_node()和Spock OSS (pgedge.com) 4点 由 pgedge_postgres 2小时前 | 隐藏 | 过去 | 收藏 | 讨论 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请YC | 联系 搜索:
相关文章

原文

pgEdge Distributed Postgres is a database system built on top of standard open‑source Postgres, extended to support global, distributed, and multi‑master (active‑active) deployments.

In the evolving landscape of distributed databases, efficient query execution across nodes is essential to leverage the full power of a distributed architecture. Specifically for distributed Postgres environments, managing a multi-node cluster often requires executing SQL commands that don’t automatically replicate. This includes critical operations like executing DDL statements, performing administrative tasks, and altering cluster configuration - actions that must be applied only on specific nodes.

To solve this operational challenge, I created the exec_node() function: a utility designed to make remote SQL execution across pgEdge nodes simple, consistent, and scriptable directly from within the database.

Why I Created exec_node()

As part of general administration tasks, there is commonly a need to execute SQL commands on a specific node or all nodes within a pgEdge distributed cluster. pgEdge leverages Spock for logical replication, but many important SQL commands—particularly the following DDL and Spock-specific cluster management functions—do not replicate by design. This includes operations like:

  • CREATE DATABASE, DROP DATABASE

  • ALTER DATABASE, ALTER SYSTEM

  • -VACUUM

  • Spock-specific commands like spock.repset_add_table, spock.node_add_interface

In a traditional setup, executing these commands safely and consistently across all or specific nodes requires manual logins, scripts, or orchestration tools. This is time-consuming and requires additional steps.

Using exec_node()

With exec_node(), you can issue commands directly from the database—through SQL—and target the exact node you want. The function signature is:

exec_node(sql text, node text DEFAULT 'all')

  • sql: The SQL command to execute.

  • node (optional): The name of the target node. Defaults to 'all', which means the command will execute on all nodes in the cluster.

With exec_node() you can:

Run SQL on Any or All Nodes — Remotely and Natively

Whether you're running a maintenance command, executing DDL statements, or configuring Spock, you can use exec_node() to do it all from a single SQL interface.

Example: Running a data maintenance command statement only on node1:

SELECT exec_node('VACUUM ANALYZE;', 'node1');

Example: Applying a maintenance operation across all nodes:

SELECT exec_node('VACUUM ANALYZE');

Execute Non-Replicating Commands Where They Belong

Some SQL commands are intentionally not replicated in pgEdge; this is either to avoid conflicts or is because they are inherently local. exec_node() allows these commands to be sent only to the relevant node(s), avoiding misconfiguration or inconsistencies.

Common non-replicating commands include:

  • ALTER SYSTEM SET

  • CREATE / DROP DATABASE

  • ALTER DATABASE SET

Example: Setting a GUC value on node 3 (only):

SELECT exec_node('ALTER SYSTEM SET log_min_duration_statement = 500; SELECT pg_reload_conf();', 'node3');

Example: Changing a GUC on all the cluster nodes:

SELECT exec_node('ALTER SYSTEM SET log_statement = ''all''; SELECT pg_reload_conf();'); SELECT exec_node('ALTER SYSTEM SET spock.enable_ddl_replication=on; SELECT pg_reload_conf();');

Execute Spock Cluster Management Functions

pgEdge clusters are built on top of the Spock extension for logical replication, but Spock management commands must be run on a specific node—and they don’t replicate. exec_node() makes this easy to automate and manage.

Example: Adding a table to a replication set:

SELECT exec_node('begin; SELECT spock.repset_add_table(''default'', ''t1''); commit;', 'node3');

Example: Creating a table on all the pgEdge nodes without adding them to the replication set:

SELECT exec_node('begin; select spock.repair_mode(true); create table t2 (a int primary key, b text); SELECT spock.repset_remove_table(''default'', ''t2''); commit;'); 

SELECT exec_node('begin; select spock.repair_mode(true); SET spock.include_ddl_repset=off; create table t2 (a int primary key, b text); commit;');

Without exec_node(), these operations would require logging into each node or writing external scripts; now they can be run as SQL from any connected client or script.

Supports Targeted DDL Deployment

Sometimes not every function or schema change is required to happen on every node. Instead,  you might want:

Example: Targeted function deployment:

SELECT exec_node('begin; SELECT spock.repair_mode(true); CREATE FUNCTION debug_info2() RETURNS text AS $$ SELECT current_database(); $$ LANGUAGE sql; commit;', 'node2');

You now have precise control over where that function lives.

Improves Automation and Operational Safety

Because exec_node() works like any SQL function, it integrates seamlessly into:

It removes the need for external scripting or SSH automation and reduces the risk of human error by centralising command execution in a controlled and auditable way.

Use Cases

Use exec_node() to help with:

  • deploying a non-replicated data maintenance command,  DDL or functions to a specific node.

  • running Spock configuration commands (repset_add_table, node_add_interface, etc.).

  • executing maintenance commands (VACUUM, REINDEX, ANALYZE) cluster-wide.

  • setting or altering system parameters per node (ALTER SYSTEM).

  • Creating or dropping databases on individual nodes.

  • Controlled rollout of feature flags or logic to subset of nodes.

Best Practices

  • Use with awareness: While powerful, be careful when executing write operations across all nodes. Ensure commands are safe / secure and do not pose risks.

  • Log executions: In automation scripts, consider logging the use of exec_node() for auditability.

  • Validate SQL: Especially when executing SQL, validate the structure and scope to avoid unintended changes.

  • Test on dev/staging: For complex cluster operations, test exec_node() in non-production environments before rollout.

The exec_node() function was designed to bridge a critical gap in managing pgEdge clusters, giving users a safe, simple, and SQL-native way to execute non-replicated operations on any node (or all nodes!) from within the database.

Whether you're managing replication sets, creating node-local functions, or automating system-wide maintenance, exec_node() provides a powerful and flexible tool to simplify your workflow and ensure operational consistency in a distributed environment.

If you’re working with pgEdge and haven’t tried it yet, exec_node() could save you hours of manual work, all while reducing the risk of mistakes.

Haven’t used pgEdge? You can self-host straight from GitHub: https://github.com/pgEdge/  Or, get an all-in-one download package on our Getting Started page: https://www.pgedge.com/get-started/platform

We welcome any feedback; get in touch with us through the pgEdge community Discord channel, anytime.

exec_node function code

 * Execute SQL on pgEdge node(s)
 * sql: sql code or statement
 * node: node name, default is `all` that will execute sql on all the cluster nodes
 *
 * Note: This function depends on dblink extension



CREATE OR REPLACE FUNCTION exec_node(sql text, node text DEFAULT 'all')
RETURNS VOID
AS $$
DECLARE
	ret text;
    r RECORD;
BEGIN
	-- CREATE EXTENSION IF NOT EXISTS dblink;
	IF node = 'all' THEN
		FOR r IN SELECT if_name, if_dsn FROM spock.node_interface LOOP
			SELECT dblink_exec(r.if_dsn, sql, false) INTO ret;
			RAISE NOTICE 'SQL `%` executed on node `%` : %', sql, r.if_name, ret;
		END LOOP;
	ELSE
		SELECT dblink_exec(if_dsn, sql, false) INTO STRICT ret FROM spock.node_interface WHERE if_name = node;
		RAISE NOTICE 'SQL `%` executed on node `%` : %', sql, node, ret;
	END IF;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        RAISE EXCEPTION 'Node `%` not found!', node;
    WHEN TOO_MANY_ROWS THEN
	-- should never happen
        RAISE EXCEPTION 'Multiple nodes found with the same name `%` !', node;
    WHEN OTHERS THEN
        RAISE EXCEPTION 'An unexpected error occurred: SQLSTATE % - %', SQLSTATE, SQLERRM;
END;
$$ LANGUAGE plpgsql;
联系我们 contact @ memedata.com