summaryrefslogtreecommitdiff
path: root/src/backend/pgxc/pool/execRemote.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/pgxc/pool/execRemote.c')
-rw-r--r--src/backend/pgxc/pool/execRemote.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c
index 43569e0e75..f065289851 100644
--- a/src/backend/pgxc/pool/execRemote.c
+++ b/src/backend/pgxc/pool/execRemote.c
@@ -1074,6 +1074,7 @@ data_node_begin(int conn_count, DataNodeHandle ** connections,
int i;
struct timeval *timeout = NULL;
RemoteQueryState *combiner;
+ TimestampTz timestamp = GetCurrentGTMStartTimestamp();
/* Send BEGIN */
for (i = 0; i < conn_count; i++)
@@ -1081,6 +1082,9 @@ data_node_begin(int conn_count, DataNodeHandle ** connections,
if (GlobalTransactionIdIsValid(gxid) && data_node_send_gxid(connections[i], gxid))
return EOF;
+ if (GlobalTimestampIsValid(timestamp) && data_node_send_timestamp(connections[i], timestamp))
+ return EOF;
+
if (data_node_send_query(connections[i], "BEGIN"))
return EOF;
}
@@ -1222,8 +1226,13 @@ data_node_commit(int conn_count, DataNodeHandle ** connections)
else
sprintf(buffer, "COMMIT PREPARED 'T%d'", gxid);
- /* We need to use a new xid, the data nodes have reset */
- two_phase_xid = BeginTranGTM();
+ /*
+ * We need to use a new xid, the data nodes have reset
+ * Timestamp has already been set with BEGIN on remote Datanodes,
+ * so don't use it here.
+ */
+ two_phase_xid = BeginTranGTM(NULL);
+
for (i = 0; i < conn_count; i++)
{
if (data_node_send_gxid(connections[i], two_phase_xid))
@@ -1338,6 +1347,7 @@ DataNodeCopyBegin(const char *query, List *nodelist, Snapshot snapshot, bool is_
bool need_tran;
GlobalTransactionId gxid;
RemoteQueryState *combiner;
+ TimestampTz timestamp = GetCurrentGTMStartTimestamp();
if (conn_count == 0)
return NULL;
@@ -1432,6 +1442,19 @@ DataNodeCopyBegin(const char *query, List *nodelist, Snapshot snapshot, bool is_
pfree(copy_connections);
return NULL;
}
+ if (conn_count == 1 && data_node_send_timestamp(connections[i], timestamp))
+ {
+ /*
+ * If a transaction involves multiple connections timestamp, is
+ * always sent down to Datanodes with data_node_begin.
+ * An autocommit transaction needs the global timestamp also,
+ * so handle this case here.
+ */
+ add_error_message(connections[i], "Can not send request");
+ pfree(connections);
+ pfree(copy_connections);
+ return NULL;
+ }
if (snapshot && data_node_send_snapshot(connections[i], snapshot))
{
add_error_message(connections[i], "Can not send request");
@@ -2027,7 +2050,8 @@ ExecRemoteQuery(RemoteQueryState *node)
bool force_autocommit = step->force_autocommit;
bool is_read_only = step->read_only;
GlobalTransactionId gxid = InvalidGlobalTransactionId;
- Snapshot snapshot = GetActiveSnapshot();
+ Snapshot snapshot = GetActiveSnapshot();
+ TimestampTz timestamp = GetCurrentGTMStartTimestamp();
DataNodeHandle **connections = NULL;
DataNodeHandle **primaryconnection = NULL;
int i;
@@ -2133,6 +2157,20 @@ ExecRemoteQuery(RemoteQueryState *node)
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("Failed to send command to data nodes")));
}
+ if (total_conn_count == 1 && data_node_send_timestamp(primaryconnection[0], timestamp))
+ {
+ /*
+ * If a transaction involves multiple connections timestamp is
+ * always sent down to Datanodes with data_node_begin.
+ * An autocommit transaction needs the global timestamp also,
+ * so handle this case here.
+ */
+ pfree(connections);
+ pfree(primaryconnection);
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("Failed to send command to data nodes")));
+ }
if (snapshot && data_node_send_snapshot(primaryconnection[0], snapshot))
{
pfree(connections);
@@ -2184,6 +2222,20 @@ ExecRemoteQuery(RemoteQueryState *node)
(errcode(ERRCODE_INTERNAL_ERROR),
errmsg("Failed to send command to data nodes")));
}
+ if (total_conn_count == 1 && data_node_send_timestamp(connections[i], timestamp))
+ {
+ /*
+ * If a transaction involves multiple connections timestamp is
+ * always sent down to Datanodes with data_node_begin.
+ * An autocommit transaction needs the global timestamp also,
+ * so handle this case here.
+ */
+ pfree(connections);
+ pfree(primaryconnection);
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("Failed to send command to data nodes")));
+ }
if (snapshot && data_node_send_snapshot(connections[i], snapshot))
{
pfree(connections);