Don't wait for statement completion when aborting coordinated transaction.

Previously we used ForgetResults() in StartRemoteTransactionAbort() -
that's problematic because there might still be an ongoing statement,
and this causes us to wait for its completion.  That e.g. happens when
a statement running on the coordinator is cancelled.
pull/1473/head
Andres Freund 2017-06-30 18:20:54 -07:00
parent 0d791f6740
commit 3461244539
1 changed files with 22 additions and 9 deletions

View File

@ -276,16 +276,21 @@ StartRemoteTransactionAbort(MultiConnection *connection)
Assert(transaction->transactionState != REMOTE_TRANS_INVALID); Assert(transaction->transactionState != REMOTE_TRANS_INVALID);
/* /*
* Clear previous results, so we have a better chance to send * Clear previous results, so we have a better chance to send ROLLBACK
* ROLLBACK [PREPARED]; * [PREPARED]. If we've previously sent a PREPARE TRANSACTION, we always
* want to wait for that result, as that shouldn't take long and will
* reserve resources. But if there's another query running, we don't want
* to wait, because a longrunning statement may be running, force it to be
* killed in that case.
*/ */
ForgetResults(connection);
if (transaction->transactionState == REMOTE_TRANS_PREPARING || if (transaction->transactionState == REMOTE_TRANS_PREPARING ||
transaction->transactionState == REMOTE_TRANS_PREPARED) transaction->transactionState == REMOTE_TRANS_PREPARED)
{ {
StringInfoData command; StringInfoData command;
/* await PREPARE TRANSACTION results, closing the connection would leave it dangling */
ForgetResults(connection);
initStringInfo(&command); initStringInfo(&command);
appendStringInfo(&command, "ROLLBACK PREPARED '%s'", appendStringInfo(&command, "ROLLBACK PREPARED '%s'",
transaction->preparedName); transaction->preparedName);
@ -304,6 +309,14 @@ StartRemoteTransactionAbort(MultiConnection *connection)
} }
else else
{ {
if (!NonblockingForgetResults(connection))
{
ShutdownConnection(connection);
/* FinishRemoteTransactionAbort will emit warning */
return;
}
if (!SendRemoteCommand(connection, "ROLLBACK")) if (!SendRemoteCommand(connection, "ROLLBACK"))
{ {
/* no point in reporting a likely redundant message */ /* no point in reporting a likely redundant message */
@ -336,17 +349,17 @@ FinishRemoteTransactionAbort(MultiConnection *connection)
ReportResultError(connection, result, WARNING); ReportResultError(connection, result, WARNING);
MarkRemoteTransactionFailed(connection, dontRaiseErrors); MarkRemoteTransactionFailed(connection, dontRaiseErrors);
if (transaction->transactionState == REMOTE_TRANS_1PC_ABORTING) if (transaction->transactionState == REMOTE_TRANS_2PC_ABORTING)
{
WarnAboutLeakedPreparedTransaction(connection, isNotCommit);
}
else
{ {
ereport(WARNING, ereport(WARNING,
(errmsg("failed to abort 1PC transaction \"%s\" on %s:%d", (errmsg("failed to abort 1PC transaction \"%s\" on %s:%d",
transaction->preparedName, connection->hostname, transaction->preparedName, connection->hostname,
connection->port))); connection->port)));
} }
else
{
WarnAboutLeakedPreparedTransaction(connection, isNotCommit);
}
} }
PQclear(result); PQclear(result);