From 5bc809466c750f93ee452bcdbe4c66c09980e915 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Fri, 1 Apr 2016 15:19:22 +0900 Subject: [PATCH] Make self-referencing foreign key on repl_nodes table deferrable --- dbutils.c | 20 ++++++++++++++++++++ repmgr.c | 2 +- sql/repmgr3.1.1_repmgr3.1.2.sql | 31 +++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 sql/repmgr3.1.1_repmgr3.1.2.sql diff --git a/dbutils.c b/dbutils.c index 834c4d71..5a378f90 100644 --- a/dbutils.c +++ b/dbutils.c @@ -1127,6 +1127,21 @@ witness_copy_node_records(PGconn *masterconn, PGconn *witnessconn, char *cluster begin_transaction(witnessconn); + /* Defer constraints */ + sqlquery_snprintf(sqlquery, "SET CONSTRAINTS ALL DEFERRED;"); + log_verbose(LOG_DEBUG, "witness_copy_node_records():\n%s\n", sqlquery); + + res = PQexec(witnessconn, sqlquery); + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) + { + log_err(_("Unable to defer constraints:\n%s\n"), + PQerrorMessage(witnessconn)); + rollback_transaction(witnessconn); + + return false; + } + + /* Truncate existing records */ sqlquery_snprintf(sqlquery, "TRUNCATE TABLE %s.repl_nodes", get_repmgr_schema_quoted(witnessconn)); log_verbose(LOG_DEBUG, "witness_copy_node_records():\n%s\n", sqlquery); @@ -1136,9 +1151,12 @@ witness_copy_node_records(PGconn *masterconn, PGconn *witnessconn, char *cluster { log_err(_("Unable to truncate witness servers's repl_nodes table:\n%s\n"), PQerrorMessage(witnessconn)); + rollback_transaction(witnessconn); + return false; } + /* Get current records from primary */ sqlquery_snprintf(sqlquery, "SELECT id, type, upstream_node_id, name, conninfo, priority, slot_name, active FROM %s.repl_nodes", get_repmgr_schema_quoted(masterconn)); @@ -1156,6 +1174,7 @@ witness_copy_node_records(PGconn *masterconn, PGconn *witnessconn, char *cluster return false; } + /* Insert primary records into witness table */ for (i = 0; i < PQntuples(res); i++) { bool node_record_created; @@ -1197,6 +1216,7 @@ witness_copy_node_records(PGconn *masterconn, PGconn *witnessconn, char *cluster } PQclear(res); + /* And finished */ commit_transaction(witnessconn); return true; diff --git a/repmgr.c b/repmgr.c index 18fd535f..6be3a3e2 100644 --- a/repmgr.c +++ b/repmgr.c @@ -4505,7 +4505,7 @@ create_schema(PGconn *conn) "CREATE TABLE %s.repl_nodes ( " " id INTEGER PRIMARY KEY, " " type TEXT NOT NULL CHECK (type IN('master','standby','witness')), " - " upstream_node_id INTEGER NULL REFERENCES %s.repl_nodes (id), " + " upstream_node_id INTEGER NULL REFERENCES %s.repl_nodes (id) DEFERRABLE, " " cluster TEXT NOT NULL, " " name TEXT NOT NULL, " " conninfo TEXT NOT NULL, " diff --git a/sql/repmgr3.1.1_repmgr3.1.2.sql b/sql/repmgr3.1.1_repmgr3.1.2.sql new file mode 100644 index 00000000..7dedacc8 --- /dev/null +++ b/sql/repmgr3.1.1_repmgr3.1.2.sql @@ -0,0 +1,31 @@ +/* + * Update a repmgr 3.1.1 installation to repmgr 3.1.2 + * -------------------------------------------------- + * + * This update is only required if repmgrd is being used in conjunction + * with a witness server. + * + * The new repmgr package should be installed first. Then + * carry out these steps: + * + * 1. (If repmgrd is used) stop any running repmgrd instances + * 2. On the master node, execute the SQL statement listed below + * 3. (If repmgrd is used) restart repmgrd + */ + +/* + * If your repmgr installation is not included in your repmgr + * user's search path, please set the search path to the name + * of the repmgr schema to ensure objects are installed in + * the correct location. + * + * The repmgr schema is "repmgr_" + the cluster name defined in + * 'repmgr.conf'. + */ + +-- SET search_path TO 'name_of_repmgr_schema'; + +BEGIN; + +ALTER TABLE repl_nodes ALTER CONSTRAINT repl_nodes_upstream_node_id_fkey DEFERRABLE; +COMMIT;