Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f78d720

Browse files
committed
Merge branch 'PGPROEE9_6_MULTIMASTER' of https://gitlab.postgrespro.ru/pgpro-dev/postgrespro into PGPROEE9_6_MULTIMASTER
2 parents d67b021 + 31612f3 commit f78d720

File tree

5 files changed

+50
-32
lines changed

5 files changed

+50
-32
lines changed

contrib/mmts/arbiter.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,7 @@ static void MtmReceiver(Datum arg)
10751075
if (ts->status != TRANSACTION_STATUS_ABORTED) {
10761076
MTM_LOG1("Arbiter receive abort message for transaction %s (%llu) from node %d", ts->gid, (long64)ts->xid, node);
10771077
Assert(ts->status == TRANSACTION_STATUS_IN_PROGRESS);
1078+
ts->aborted_by_node = node;
10781079
MtmAbortTransaction(ts);
10791080
}
10801081
if ((ts->participantsMask & ~Mtm->disabledNodeMask & ~ts->votedMask) == 0) {

contrib/mmts/multimaster--1.0.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ CREATE FUNCTION mtm.referee_poll(xid bigint) RETURNS bigint
112112
AS 'MODULE_PATHNAME','mtm_referee_poll'
113113
LANGUAGE C;
114114

115-
CREATE TABLE IF NOT EXISTS mtm.local_tables(rel_schema text, rel_name text, primary key(rel_schema, rel_name));
115+
CREATE TABLE IF NOT EXISTS mtm.local_tables(rel_schema name, rel_name name, primary key(rel_schema, rel_name));
116116

117117
CREATE OR REPLACE FUNCTION mtm.alter_sequences() RETURNS boolean AS
118118
$$

contrib/mmts/multimaster.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,15 @@ void MtmReleaseLocks(void)
318318
* locks[N+1..2*N] are used to synchronize access to distributed lock graph at each node
319319
* -------------------------------------------
320320
*/
321+
322+
//#define DEBUG_MTM_LOCK 1
323+
324+
#if DEBUG_MTM_LOCK
321325
static timestamp_t MtmLockLastReportTime;
322326
static timestamp_t MtmLockElapsedWaitTime;
323327
static timestamp_t MtmLockMaxWaitTime;
324328
static size_t MtmLockHitCount;
325-
326-
//#define DEBUG_MTM_LOCK 1
329+
#endif
327330

328331
void MtmLock(LWLockMode mode)
329332
{
@@ -911,14 +914,15 @@ MtmResetTransaction()
911914
x->gid[0] = '\0';
912915
}
913916

914-
917+
#if 0
915918
static const char* const isoLevelStr[] =
916919
{
917920
"read uncommitted",
918921
"read committed",
919922
"repeatable read",
920923
"serializable"
921924
};
925+
#endif
922926

923927
bool MtmTransIsActive(void)
924928
{
@@ -2586,8 +2590,8 @@ void MtmMakeTableLocal(char const* schema, char const* name)
25862590

25872591

25882592
typedef struct {
2589-
text schema;
2590-
text name;
2593+
NameData schema;
2594+
NameData name;
25912595
} MtmLocalTablesTuple;
25922596

25932597
static void MtmLoadLocalTables(void)
@@ -2607,7 +2611,7 @@ static void MtmLoadLocalTables(void)
26072611
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
26082612
{
26092613
MtmLocalTablesTuple *t = (MtmLocalTablesTuple*) GETSTRUCT(tuple);
2610-
MtmMakeTableLocal(text_to_cstring(&t->schema), text_to_cstring(&t->name));
2614+
MtmMakeTableLocal(NameStr(t->schema), NameStr(t->name));
26112615
}
26122616

26132617
systable_endscan(scan);
@@ -2771,6 +2775,10 @@ void MtmUpdateNodeConnectionInfo(MtmConnectionInfo* conn, char const* connStr)
27712775
MTM_ELOG(ERROR, "Too long (%d) connection string '%s': limit is %d",
27722776
connStrLen, connStr, MULTIMASTER_MAX_CONN_STR_SIZE-1);
27732777
}
2778+
2779+
while(isspace(*connStr))
2780+
connStr++;
2781+
27742782
strcpy(conn->connStr, connStr);
27752783

27762784
host = strstr(connStr, "host=");
@@ -4795,8 +4803,12 @@ static bool MtmTwoPhaseCommit(MtmCurrentTrans* x)
47954803
} else {
47964804
Assert(x->isActive);
47974805
if (x->status == TRANSACTION_STATUS_ABORTED) {
4806+
MtmTransState* ts;
4807+
ts = (MtmTransState*) hash_search(MtmXid2State, &(x->xid), HASH_FIND, NULL);
4808+
Assert(ts);
4809+
47984810
FinishPreparedTransaction(x->gid, false);
4799-
MTM_ELOG(ERROR, "Transaction %s (%llu) is aborted by DTM", x->gid, (long64)x->xid);
4811+
MTM_ELOG(ERROR, "Transaction %s (%llu) is aborted on node %d. Check its log to see error details.", x->gid, (long64)x->xid, ts->aborted_by_node);
48004812
} else {
48014813
FinishPreparedTransaction(x->gid, true);
48024814
MTM_LOG2("Distributed transaction %s (%lld) is committed at %lld with LSN=%lld", x->gid, (long64)x->xid, MtmGetCurrentTime(), (long64)GetXLogInsertRecPtr());

contrib/mmts/multimaster.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ typedef struct MtmTransState
267267
nodemask_t participantsMask; /* Mask of nodes involved in transaction */
268268
nodemask_t votedMask; /* Mask of voted nodes */
269269
TransactionId xids[1]; /* [Mtm->nAllNodes]: transaction ID at replicas */
270+
int aborted_by_node; /* Store info about node on which this tx was aborted */
270271
} MtmTransState;
271272

272273
typedef struct {

doc/src/sgml/multimaster.sgml

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -430,11 +430,11 @@ multimaster.conn_strings = 'dbname=mydb user=myuser host=node1, dbname=mydb user
430430
# of connection strings
431431
# to neighbor nodes
432432
</programlisting>
433-
<para>The <literal>multimaster.max_nodes</literal> variable defines the maximum cluster size. If you plan to add new nodes to your cluster, the <literal>multimaster.max_nodes</literal> value should exceed the initial number of nodes. In this case, you can add new nodes without restarting <productname>&productname;</productname>.
433+
<para>The <literal>multimaster.max_nodes</literal> variable defines the maximum cluster size. If you plan to add new nodes to your cluster, the <literal>multimaster.max_nodes</literal> value should exceed the initial number of nodes. In this case, you can add new nodes without restarting <productname>&productname;</productname> until the specified number of nodes is reached.
434434
</para>
435435
<para>In most cases, three cluster nodes are enough to ensure high availability. Since the data on all cluster nodes is the same, you do not typically need more than five cluster nodes.
436436
</para>
437-
<para>If you would like to change the default connection settings for a cluster node, you can add other <link linkend="libpq-paramkeywords"> connection parameters</link> to the corresponding connection string in the <varname>multimaster.conn_strings</varname> variable. Additionally, you can specify the <literal>arbiter_process</literal> parameter to change the port used by the arbiter process to connect to the nodes. For details, see <xref linkend="multimaster-conn-strings"> and <xref linkend="multimaster-arbiter-port">.</para>
437+
<para>If you would like to change the default connection settings for a cluster node, you can add other <link linkend="libpq-paramkeywords"> connection parameters</link> to the corresponding connection string in the <varname>multimaster.conn_strings</varname> variable. If you change the default port on which the arbiter process listens for connections, you must specify this port in the <literal>arbiter_port</literal> parameter. For details, see <xref linkend="multimaster-arbiter-port"> and <xref linkend="multimaster-conn-strings">.</para>
438438
<important><para>The
439439
<literal>multimaster.node_id</literal> variable takes natural
440440
numbers starting from 1, without any gaps in numbering.
@@ -480,7 +480,7 @@ CREATE EXTENSION multimaster;</programlisting></para>
480480
the <structname>mtm.get_cluster_state()</structname> view:
481481
</para>
482482
<programlisting>
483-
SELECT * FROM mtm.get_cluster_state();
483+
mtm.get_cluster_state();
484484
</programlisting>
485485
<para>
486486
If <literal>liveNodes</literal> is equal to
@@ -611,22 +611,24 @@ SELECT * FROM mtm.get_cluster_state();
611611
To check node-specific information, use <literal>mtm.get_nodes_state()</literal>:
612612
</para>
613613
<programlisting>
614-
SELECT * FROM mtm.get_nodes_state();
614+
mtm.get_nodes_state();
615615
</programlisting>
616616
<para>To check the status of the whole cluster, use the
617617
<literal>mtm.get_cluster_state()</literal> view:
618618
</para>
619619
<programlisting>
620-
SELECT * FROM mtm.get_cluster_state();
620+
mtm.get_cluster_state();
621621
</programlisting>
622622
<para>For details on all the returned information, see <xref linkend="multimaster-functions">.
623623
</para>
624624
</sect3>
625625
<sect3 id="multimaster-adding-new-nodes-to-the-cluster">
626626
<title>Adding New Nodes to the Cluster</title>
627+
<para>With the <filename>multimaster</filename> extension, you can add or drop cluster nodes without
628+
stopping the database service.
629+
</para>
627630
<para>
628-
With multimaster, you can add or drop cluster nodes without a
629-
restart. To add a new node, you need to change the cluster
631+
To add a new node, you need to change the cluster
630632
configuration on alive nodes, load all the data to the new node using
631633
<application>pg_basebackup</application>, and start the node.
632634
</para>
@@ -637,21 +639,30 @@ SELECT * FROM mtm.get_cluster_state();
637639
<literal>node4</literal>, follow these steps:
638640
</para>
639641
<orderedlist>
642+
<listitem>
643+
<para>Check whether the current number of cluster nodes has reached the value specified in the
644+
<varname>multimaster.max_nodes</varname> variable. If this value is reached, increase
645+
the <varname>multimaster.max_nodes</varname> value on each node and restart all nodes.
646+
You can restart the nodes one by one, without stopping the database.
647+
If the maximum number of nodes is not reached, proceed to the next step.
648+
</para>
649+
</listitem>
640650
<listitem>
641651
<para>
642652
Figure out the required connection string to
643653
access the new node. For example, for the database
644654
<literal>mydb</literal>, user <literal>myuser</literal>, and
645655
the new node <literal>node4</literal>, the connection string
646-
is <literal>&quot;dbname=mydb user=myuser host=node4&quot;</literal>.
656+
can be <literal>&quot;dbname=mydb user=myuser host=node4&quot;</literal>.
657+
For details, see <xref linkend="multimaster-conn-strings">.
647658
</para>
648659
</listitem>
649660
<listitem>
650661
<para>
651662
In <literal>psql</literal> connected to any alive node, run:
652663
</para>
653664
<programlisting>
654-
SELECT * FROM mtm.add_node('dbname=mydb user=myuser host=node4');
665+
mtm.add_node('dbname=mydb user=myuser host=node4');
655666
</programlisting>
656667
<para>
657668
This command changes the cluster configuration on all nodes
@@ -677,7 +688,6 @@ pg_basebackup -D <replaceable>datadir</replaceable> -h node1 -x
677688
<literal>node4</literal>:
678689
</para>
679690
<programlisting>
680-
multimaster.max_nodes = 4
681691
multimaster.node_id = 4
682692
multimaster.conn_strings = 'dbname=mydb user=myuser host=node1, dbname=mydb user=myuser host=node2,
683693
dbname=mydb user=myuser host=node3, dbname=mydb user=myuser host=node4'
@@ -700,7 +710,7 @@ pg_ctl -D <replaceable>datadir</replaceable> -l <replaceable>pg.log</replaceable
700710
<orderedlist>
701711
<listitem>
702712
<para>
703-
Change <literal>multimaster.conn_strings</literal> and <literal>multimaster.max_nodes</literal> to include the new node.
713+
Change <literal>multimaster.conn_strings</literal> to include the new node.
704714
</para>
705715
</listitem>
706716
<listitem>
@@ -709,11 +719,6 @@ pg_ctl -D <replaceable>datadir</replaceable> -l <replaceable>pg.log</replaceable
709719
replication to the new node.
710720
</para>
711721
</listitem>
712-
<listitem>
713-
<para>
714-
Restart all cluster nodes.
715-
</para>
716-
</listitem>
717722
</orderedlist>
718723
<para>
719724
<emphasis role="strong">See Also</emphasis></para>
@@ -757,7 +762,7 @@ SELECT mtm.stop_node(3);
757762
In <literal>psql</literal> connected to any alive node, create a new replication slot for the disconnected node with the following command:
758763
</para>
759764
<programlisting>
760-
SELECT * FROM mtm.recover_node(2);
765+
mtm.recover_node(2);
761766
</programlisting>
762767
<para>where 2 is the ID of the disconnected node specified in the <varname>multimaster.node_id</varname> variable.</para>
763768
</listitem>
@@ -814,19 +819,18 @@ pg_ctl -D <replaceable>datadir</replaceable> -l <replaceable>pg.log</replaceable
814819
Connection strings must appear in the order of the node IDs
815820
specified in the <varname>multimaster.node_id</varname> variable.
816821
Connection string for the i-th node must be on the i-th position.
817-
You can also specify a
818-
custom port for the arbiter to listen on using the <literal>arbiter_port</literal>
819-
parameter. The provided value must be the same as the <varname>multimaster.arbiter_port</varname>
820-
value specified for this node.
822+
If you specify a custom port in the <varname>multimaster.arbiter_port</varname>,
823+
you must provide this value in the <literal>arbiter_port</literal>
824+
parameter in the connection string for the corresponding node.
821825
</para></listitem></varlistentry>
822826
<varlistentry><term><varname>multimaster.max_nodes</varname><indexterm><primary><varname>multimaster.max_nodes</varname></primary></indexterm></term><listitem><para>
823-
The maximum number of nodes allowed in the cluster. If you plan to add new nodes to your cluster, the <literal>multimaster.max_nodes</literal> value should exceed the initial number of nodes. In this case, you can add new nodes without restarting <productname>&productname;</productname>. In most cases, three cluster nodes are enough to ensure high availability. Since the data on all cluster nodes is the same, you do not typically need more than five cluster nodes. The maximum possible number of nodes is limited to 64.</para>
827+
The maximum number of nodes allowed in the cluster. If you plan to add new nodes to your cluster, the <literal>multimaster.max_nodes</literal> value should exceed the initial number of nodes. In this case, you can add new nodes without restarting <productname>&productname;</productname> until the specified number of nodes is reached. In most cases, three cluster nodes are enough to ensure high availability. Since the data on all cluster nodes is the same, you do not typically need more than five cluster nodes. The maximum possible number of nodes is limited to 64.</para>
824828
<para>Default: the number of nodes specified in the <varname>multimaster.conn_strings</varname> variable
825829
</para></listitem></varlistentry>
826830
<varlistentry id="multimaster-arbiter-port">
827831
<term><varname>multimaster.arbiter_port</varname><indexterm><primary><varname>multimaster.arbiter_port</varname></primary></indexterm></term><listitem><para>
828832
Port for the arbiter process to listen on. If you change the default value, you must specify this value in the <literal>arbiter_port</literal>
829-
parameter in the connection string of the corresponding node.</para>
833+
parameter in the connection string for the corresponding node.</para>
830834
<para>Default: 5433
831835
</para></listitem></varlistentry>
832836
<varlistentry><term><varname>multimaster.heartbeat_send_timeout</varname><indexterm><primary><varname>multimaster.heartbeat_send_timeout</varname></primary></indexterm></term><listitem><para>
@@ -873,7 +877,7 @@ pg_ctl -D <replaceable>datadir</replaceable> -l <replaceable>pg.log</replaceable
873877
</para></listitem></varlistentry>
874878
<varlistentry><term><varname>multimaster.cluster_name</varname><indexterm><primary><varname>multimaster.cluster_name</varname></primary></indexterm></term><listitem><para>
875879
Name of the cluster. If
876-
you set this variable, <filename>multimaster</filename> checks that
880+
you define this variable when setting up the cluster, <filename>multimaster</filename> checks that
877881
the cluster name is the same for all the cluster nodes.
878882
</para></listitem></varlistentry>
879883
<varlistentry>

0 commit comments

Comments
 (0)