diff options
Diffstat (limited to 'contrib/postgres_fdw/connection.c')
-rw-r--r-- | contrib/postgres_fdw/connection.c | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c index 66581e54144..d841cec39b5 100644 --- a/contrib/postgres_fdw/connection.c +++ b/contrib/postgres_fdw/connection.c @@ -940,12 +940,14 @@ pgfdw_xact_callback(XactEvent event, void *arg) entry->xact_depth = 0; /* - * If the connection isn't in a good idle state, discard it to - * recover. Next GetConnection will open a new connection. + * If the connection isn't in a good idle state or it is marked as + * invalid, then discard it to recover. Next GetConnection will open a + * new connection. */ if (PQstatus(entry->conn) != CONNECTION_OK || PQtransactionStatus(entry->conn) != PQTRANS_IDLE || - entry->changing_xact_state) + entry->changing_xact_state || + entry->invalidated) { elog(DEBUG3, "discarding connection %p", entry->conn); disconnect_pg_server(entry); @@ -1069,9 +1071,12 @@ pgfdw_subxact_callback(SubXactEvent event, SubTransactionId mySubid, * Connection invalidation callback function * * After a change to a pg_foreign_server or pg_user_mapping catalog entry, - * mark connections depending on that entry as needing to be remade. - * We can't immediately destroy them, since they might be in the midst of - * a transaction, but we'll remake them at the next opportunity. + * close connections depending on that entry immediately if current transaction + * has not used those connections yet. Otherwise, mark those connections as + * invalid and then make pgfdw_xact_callback() close them at the end of current + * transaction, since they cannot be closed in the midst of the transaction + * using them. Closed connections will be remade at the next opportunity if + * necessary. * * Although most cache invalidation callbacks blow away all the related stuff * regardless of the given hashvalue, connections are expensive enough that @@ -1102,7 +1107,21 @@ pgfdw_inval_callback(Datum arg, int cacheid, uint32 hashvalue) entry->server_hashvalue == hashvalue) || (cacheid == USERMAPPINGOID && entry->mapping_hashvalue == hashvalue)) - entry->invalidated = true; + { + /* + * Close the connection immediately if it's not used yet in this + * transaction. Otherwise mark it as invalid so that + * pgfdw_xact_callback() can close it at the end of this + * transaction. + */ + if (entry->xact_depth == 0) + { + elog(DEBUG3, "discarding connection %p", entry->conn); + disconnect_pg_server(entry); + } + else + entry->invalidated = true; + } } } |