Chapter 9. MySQL Cluster Replication
Table of Contents
- 9.1. MySQL Cluster Replication — Abbreviations and Symbols
- 9.2. MySQL Cluster Replication — Assumptions and General Requirements
- 9.3. Known Issues in MySQL Cluster Replication
- 9.4. MySQL Cluster Replication Schema and Tables
- 9.5. Preparing the MySQL Cluster for Replication
- 9.6. Starting MySQL Cluster Replication (Single Replication Channel)
- 9.7. Using Two Replication Channels for MySQL Cluster Replication
- 9.8. Implementing Failover with MySQL Cluster Replication
- 9.9. MySQL Cluster Backups With MySQL Cluster Replication
- 9.10. MySQL Cluster Replication — Multi-Master and Circular Replication
- 9.11. MySQL Cluster Replication Conflict Resolution
Previous to MySQL 5.1.6, asynchronous replication, more usually referred to simply as “replication”, was not available when using MySQL Cluster. MySQL 5.1.6 introduces master-slave replication of this type for MySQL Cluster databases. This section explains how to set up and manage a configuration wherein one group of computers operating as a MySQL Cluster replicates to a second computer or group of computers. We assume some familiarity on the part of the reader with standard MySQL replication as discussed elsewhere in this Manual. (See Replication).
Normal (nonclustered) replication involves a “master”
server and a “slave” server, the master being the
source of the operations and data to be replicated and the slave
being the recipient of these. In MySQL Cluster, replication is
conceptually very similar but can be more complex in practice, as it
may be extended to cover a number of different configurations
including replicating between two complete clusters. Although a
MySQL Cluster itself depends on the
NDBCLUSTER storage engine for
clustering functionality, it is not necessary to use the Cluster
storage engine on the slave. However, for maximum availability, it
is possible to replicate from one MySQL Cluster to another, and it
is this type of configuration that we discuss, as shown in the
following figure:

In this scenario, the replication process is one in which successive
states of a master cluster are logged and saved to a slave cluster.
This process is accomplished by a special thread known as the NDB
binlog injector thread, which runs on each MySQL server and produces
a binary log (binlog). This thread ensures that
all changes in the cluster producing the binary log — and not
just those changes that are effected via the MySQL Server —
are inserted into the binary log with the correct serialization
order. We refer to the MySQL replication master and replication
slave servers as replication servers or replication nodes, and the
data flow or line of communication between them as a
replication channel.
Throughout this section, we use the following abbreviations or symbols for referring to the master and slave clusters, and to processes and commands run on the clusters or cluster nodes:
| Symbol or Abbreviation | Description (Refers to...) |
M | The cluster serving as the (primary) replication master |
S | The cluster acting as the (primary) replication slave |
shell | Shell command to be issued on the master cluster |
mysql | MySQL client command issued on a single MySQL server running as an SQL node on the master cluster |
mysql | MySQL client command to be issued on all SQL nodes participating in the replication master cluster |
shell | Shell command to be issued on the slave cluster |
mysql | MySQL client command issued on a single MySQL server running as an SQL node on the slave cluster |
mysql | MySQL client command to be issued on all SQL nodes participating in the replication slave cluster |
C | Primary replication channel |
C' | Secondary replication channel |
M' | Secondary replication master |
S' | Secondary replication slave |
A replication channel requires two MySQL servers acting as replication servers (one each for the master and slave). For example, this means that in the case of a replication setup with two replication channels (to provide an extra channel for redundancy), there will be a total of four replication nodes, two per cluster.
Replication of a MySQL Cluster as described in this section and
those following is dependent on row-based replication. This means
that the replication master MySQL server must be started with
--binlog-format=ROW or
--binlog-format=MIXED, as described
in Section 9.6, “Starting MySQL Cluster Replication (Single Replication Channel)”. For
general information about row-based replication, see
Replication Formats.
Important
If you attempt to use MySQL Cluster Replication with
--binlog-format=STATEMENT,
replication fails to work properly because the
ndb_binlog_index table on the master and the
epoch column of the
ndb_apply_status table on the slave are not
updated (see
Section 9.4, “MySQL Cluster Replication Schema and Tables”). Instead,
only updates on the MySQL server acting as the replication
master propagate to the slave, and no updates from any other SQL
nodes on the master cluster are replicated.
In all MySQL Cluster NDB 6.x releases, the default value for the
--binlog-format option is
MIXED.
Each MySQL server used for replication in either cluster must be
uniquely identified among all the MySQL replication servers
participating in either cluster (you cannot have replication
servers on both the master and slave clusters sharing the same
ID). This can be done by starting each SQL node using the
--server-id=
option, where idid is a unique integer.
Although it is not strictly necessary, we will assume for purposes
of this discussion that all MySQL installations are the same
version.
In any event, both MySQL servers involved in replication must be compatible with one another with respect to both the version of the replication protocol used and the SQL feature sets which they support; the simplest and easiest way to assure that this is the case is to use the same MySQL version for all servers involved. Note that in many cases it is not possible to replicate to a slave running a version of MySQL with a lower version number than that of the master — see Replication Compatibility Between MySQL Versions, for details.
We assume that the slave server or cluster is dedicated to replication of the master, and that no other data is being stored on it.
Note
It is possible to replicate a MySQL Cluster using statement-based replication. However, in this case, the following restrictions apply:
All updates to data rows on the cluster acting as the master must be directed to a single MySQL server.
It is not possible to replicate a cluster using multiple simultaneous MySQL replication processes.
Only changes made at the SQL level are replicated.
These are in addition to the other limitations of statement-based replication as opposed to row-based replication; see Comparison of Statement-Based and Row-Based Replication, for more specific information concerning the differences between the two replication formats.
The following are known problems or issues when using replication with MySQL Cluster in MySQL 5.1:
Loss of master-slave connection. Prior to MySQL 5.1.18, a MySQL Cluster replication slave mysqld had no way of detecting that the connection from the master had been interrupted (due to, for instance, the master going down or a network failure). For this reason, it was possible for the slave to become inconsistent with the master.
Beginning with MySQL 5.1.18, the master issues a “gap” event when connecting to the cluster. When the slave encounters a gap in the replication log, it stops with an error message. This message is available in the output of
SHOW SLAVE STATUS, and indicates that the SQL thread has stopped due to an incident registered in the replication stream, and that manual intervention is required. In order to restart the slave, it is necessary to issue the following commands:SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;
The slave then resumes reading the master binlog from the point where the gap was recorded.
Important
If high availability is a requirement for the slave server or cluster, then it is still advisable to set up multiple replication lines, to monitor the master mysqld on the primary replication line, and to fail over to a secondary line if and as necessary. For information about implementing this type of setup, see Section 9.7, “Using Two Replication Channels for MySQL Cluster Replication”, and Section 9.8, “Implementing Failover with MySQL Cluster Replication”.
However, if you are replicating from a standalone MySQL server to a MySQL Cluster, one channel is usually sufficient.
Multi-byte character sets. There are several known issues with regard to the use of multi-byte characters sets with MySQL Cluster Replication. See Bug#27404 (fixed in MySQL 5.1.21), Bug#29562, Bug#29563, and Bug#29564 for more information.
Circular replication. Prior to MySQL 5.1.18, circular replication was not supported with MySQL Cluster replication, due to the fact that all log events created in a particular MySQL Cluster were wrongly tagged with the server ID of the MySQL server used as master and not with the server ID of the originating server.
Beginning with MySQL 5.1.18, this limitation is lifted, as discussed in the next few paragraphs, in which we consider the example of a replication setup involving three MySQL Clusters numbered 1, 2, and 3, in which Cluster 1 acts as the replication master for Cluster 2, Cluster 2 acts as the master for Cluster 3, and Cluster 3 acts as the master for Cluster 1. Each cluster has two SQL nodes, with SQL nodes A and B belonging to Cluster 1, SQL nodes C and D belonging to Cluster 2, and SQL nodes E and F belonging to Cluster 3.
Circular replication using these clusters is supported as long as:
The SQL nodes on all masters and slaves are the same
All SQL nodes acting as replication masters and slaves are started using the
--log-slave-updatesoption
This type of circular replication setup is shown in the following diagram:

In this scenario, SQL node A in Cluster 1 replicates to SQL node C in Cluster 2; SQL node C replicates to SQL node E in Cluster 3; SQL node E replicates to SQL node A. In other words, the replication line (indicated by the red arrows in the diagram) directly connects all SQL nodes used as replication masters and slaves.
It should also be possible to set up circular replication in which not all master SQL nodes are also slaves, as shown here:

In this case, different SQL nodes in each cluster are used as replication masters and slaves. However, you must not start any of the SQL nodes using
--log-slave-updates(see the description of this option for more information). This type of circular replication scheme for MySQL Cluster, in which the line of replication (again indicated by the red arrows in the diagram) is discontinuous, should be possible, but it should be noted that it has not yet been thoroughly tested and must therefore still be considered experimental.Important
Beginning with MySQL 5.1.24, you should execute the following statement before starting circular replication:
mysql>
SET GLOBAL slave_exec_mode = 'IDEMPOTENT';This is necessary to suppress duplicate-key and other errors that otherwise break circular replication of MySQL Cluster.
IDEMPOTENTmode is also required for multi-master replication when using MySQL Cluster. (Bug#31609)See
slave_exec_mode, for more information.DDL statements. The use of data definition statements, such as
CREATE TABLE,DROP TABLE, andALTER TABLE, are recorded in the binary log for only the MySQL server on which they are issued.Cluster replication and primary keys. In MySQL 5.1.6, only those
NDBtables having explicit primary keys could be replicated. This limitation was lifted in MySQL 5.1.7. However, in the event of a node failure, errors in replication ofNDBtables without primary keys can still occur, due to the possibility of duplicate rows being inserted in such cases. For this reason, it is highly recommended that allNDBtables being replicated have primary keys.Restarting with
--initial. Restarting the cluster with the--initialoption causes the sequence of GCI and epoch numbers to start over from0. (This is generally true of MySQL Cluster and not limited to replication scenarios involving Cluster.) The MySQL servers involved in replication should in this case be restarted. After this, you should use theRESET MASTERandRESET SLAVEstatements to clear the invalidndb_binlog_indexandndb_apply_statustables. respectively.auto_increment_offsetandauto_increment_incrementvariables. The use of theauto_increment_offsetandauto_increment_incrementserver system variables is supported beginning with MySQL 5.1.20. Previously, these produced unpredictable results when used withNDBtables or MySQL Cluster replication.Replication from
NDBCLUSTERto other storage engines. If you attempt to replicate from a MySQL Cluster to a slave that uses a storage engine that does not handle its own binary logging, the replication process aborts with the error Binary logging not possible ... Statement cannot be written atomically since more than one engine involved and at least one engine is self-logging (Error 1595). It is possible to work around this issue in one of the following ways:Turn off binary logging on the slave. This can be accomplished by setting
sql_log_bin = 0.Change the storage engine used for the
mysql.ndb_apply_statustable. Causing this table to use an engine that does not handle its own binary logging can also eliminate the conflict. This can be done by issuing a statement such asALTER TABLE mysql.ndb_apply_status ENGINE=MyISAMon the slave. It is safe to do this when using a non-NDBstorage engine on the slave, since you do not then need to worry about keeping multiple slave SQL nodes synchronized.Filter out changes to the
mysql.ndb_apply_statustable on the slave. This can be done by starting the slave SQL node with the option--replicate-ignore-table=mysql.ndb_apply_status. If you need for other tables to be ignored by replication, you might wish to use an appropriate--replicate-wild-ignore-tableoption instead.
Important
You should not disable replication or binary logging of
mysql.ndb_apply_statusor change the storage engine used for this table when replicating from one MySQL Cluster to another. See Replication and binary log filtering rules with replication between MySQL Clusters elsewhere in this section for details.When replicating from
NDBCLUSTERto a nontransactional storage engine such asMyISAM, you may encounter unnecessary duplicate key errors when replicatingINSERT ... ON DUPLICATE KEY UPDATEstatements. You can suppress these in MySQL Cluster NDB 6.2 by using--ndb-log-update-as-write=0, which forces all columns from updated rows to be sent (and not just those that were updated). For MySQL Cluster NDB 6.3.3 and later, there are additional way to determine whether or not an update to the row on the master should be applied on the slave mysqld; see Section 9.11, “MySQL Cluster Replication Conflict Resolution”, for more information about these methods.Replication and binary log filtering rules with replication between MySQL Clusters. If you are using any of the options
--replicate-do-*,--replicate-ignore-*,--binlog-do-db, or--binlog-ignore-dbto filter databases or tables being replicated, care must be taken not to block replication or binary logging of themysql.ndb_apply_status, which is required for replication between MySQL Clusters to operate properly. In particular, you must keep in mind the following:Using
--replicate-do-db=(and no otherdb_name--replicate-do-*or--replicate-ignore-*options) means that only tables in databasedb_nameare replicated. In this case, you should also use--replicate-do-db=mysql,--binlog-do-db=mysql, or--replicate-do-table=mysql.ndb_apply_statusto insure thatmysql.ndb_apply_statusis populated on slaves.Using
--binlog-do-db=(and no otherdb_name--binlog-do-dboptions) means that changes only to tables in databasedb_nameare written to the binary log. In this case, you should also use--replicate-do-db=mysql,--binlog-do-db=mysql, or--replicate-do-table=mysql.ndb_apply_statusto insure thatmysql.ndb_apply_statusis populated on slaves.Using
--replicate-ignore-db=mysqlmeans that no tables in themysqldatabase are replicated. In this case, you should also use--replicate-do-table=mysql.ndb_apply_statusto insure thatmysql.ndb_apply_statusis replicated.Using
--binlog-ignore-db=mysqlmeans that no changes to tables in themysqldatabase are written to the binary log. In this case, you should also use--replicate-do-table=mysql.ndb_apply_statusto insure thatmysql.ndb_apply_statusis replicated.
You should also remember that:
Each replication filtering rule requires its own
--replicate-do-*or--replicate-ignore-*option, and that multiple rules cannot be expressed in a single replication filtering option. For information about these rules, see Replication and Binary Logging Options and Variables.Each binary log filtering rule requires its own
--binlog-do-dbor--binlog-ignore-dboption, and that multiple rules cannot be expressed in a single binary log filtering option. For information about these rules, see The Binary Log.
Note
If you are replicating a MySQL Cluster to a slave that uses a storage engine other than
NDBCLUSTER, the considerations just given previously may not apply. See Replication fromNDBCLUSTERto other storage engines elsewhere in this section for details.MySQL Cluster Replication and IPv6. Currently, the NDB API and MGM API do not support IPv6. However, beginning with MySQL Cluster NDB 6.4.1, MySQL Servers — including those acting as SQL nodes in a MySQL Cluster — can use IPv6 to contact other MySQL Servers. This means that you can replicate between MySQL Clusters using IPv6 to connect the master and slave SQL nodes as shown by the dotted arrow in the following diagram:

However, all connections originating within the MySQL Cluster — shown in the diagram by solid arrows — must use IPv4.
All MySQL Cluster data nodes, management servers, and management clients must be accessible from one another using IPv4. In addition, SQL nodes must use IPv4 to communicate with the cluster. There is not currently any support in the NDB and MGM APIs for IPv6, which means that any applications written using these APIs must also make all connections using IPv4.
Replication in MySQL Cluster makes use of a number of dedicated
tables in the mysql database on each MySQL
Server instance acting as an SQL node in both the cluster being
replicated and the replication slave (whether the slave is a
single server or a cluster). These tables are created during the
MySQL installation process by the
mysql_install_db script, and include a table
for storing the binary log's indexing data. Since the
ndb_binlog_index table is local to each MySQL
server and does not participate in clustering, it uses the
MyISAM storage engine. This means that it must
be created separately on each mysqld
participating in the master cluster. (However, the binlog itself
contains updates from all MySQL servers in the cluster to be
replicated.) This table is defined as follows:
CREATE TABLE `ndb_binlog_index` (
`Position` BIGINT(20) UNSIGNED NOT NULL,
`File` VARCHAR(255) NOT NULL,
`epoch` BIGINT(20) UNSIGNED NOT NULL,
`inserts` BIGINT(20) UNSIGNED NOT NULL,
`updates` BIGINT(20) UNSIGNED NOT NULL,
`deletes` BIGINT(20) UNSIGNED NOT NULL,
`schemaops` BIGINT(20) UNSIGNED NOT NULL,
PRIMARY KEY (`epoch`)
) ENGINE=MYISAM DEFAULT CHARSET=latin1;
Important
Prior to MySQL 5.1.14, the ndb_binlog_index
table was known as binlog_index, and was kept
in a separate cluster database, which in
MySQL 5.1.7 and earlier was known as the
cluster_replication database. Similarly, the
ndb_apply_status and
ndb_schema tables were known as
apply_status and schema,
and were also found in the cluster (earlier
cluster_replication) database. However,
beginning with MySQL 5.1.14, all MySQL Cluster replication
tables reside in the mysql system database.
Information about how this change affects upgrades from MySQL Cluster 5.1.13 and earlier to 5.1.14 and later versions can be found in Changes in MySQL 5.1.14.
Beginning with MySQL Cluster NDB 6.3.2, this table has been
changed to facilitate 3-way replication recovery. Two columns
orig_server_id and
orig_epoch have been added to this table; when
mysqld is started with the
--ndb-log-orig option, these columns store,
respectively, the ID of the server on which the event originated
and the epoch in which the event took place on the originating
server. In addition, the table's primary key now includes
these two columns. The modified table definition is shown here:
CREATE TABLE `ndb_binlog_index` (
`Position` BIGINT(20) UNSIGNED NOT NULL,
`File` VARCHAR(255) NOT NULL,
`epoch` BIGINT(20) UNSIGNED NOT NULL,
`inserts` INT(10) UNSIGNED NOT NULL,
`updates` INT(10) UNSIGNED NOT NULL,
`deletes` INT(10) UNSIGNED NOT NULL,
`schemaops` INT(10) UNSIGNED NOT NULL,
`orig_server_id` INT(10) UNSIGNED NOT NULL,
`orig_epoch` BIGINT(20) UNSIGNED NOT NULL,
`gci` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`epoch`,`orig_server_id`,`orig_epoch`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
The gci column was added in MySQL Cluster NDB
6.2.6 and MySQL Cluster NDB 6.3.2.
The following figure shows the relationship of the MySQL Cluster
replication master server, its binlog injector thread, and the
mysql.ndb_binlog_index table.

An additional table, named ndb_apply_status, is
used to keep a record of the operations that have been replicated
from the master to the slave. Unlike the case with
ndb_binlog_index, the data in this table is not
specific to any one SQL node in the (slave) cluster, and so
ndb_apply_status can use the NDB
Cluster storage engine, as shown here:
CREATE TABLE `ndb_apply_status` (
`server_id` INT(10) UNSIGNED NOT NULL,
`epoch` BIGINT(20) UNSIGNED NOT NULL,
`log_name` VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
`start_pos` BIGINT(20) UNSIGNED NOT NULL,
`end_pos` BIGINT(20) UNSIGNED NOT NULL,
PRIMARY KEY (`server_id`) USING HASH
) ENGINE=NDBCLUSTER DEFAULT CHARSET=latin1;
This table is populated only on slaves; on the master, no
DataMemory is allocated to it. However, the
table is populated from the master. For this
reason, this table must be replicated and any replication
filtering or binary log filtering rules that prevent this prevent
replication between clusters from operating properly. For more
information about potential problems arising from such filtering
rules, see Section 9.3, “Known Issues in MySQL Cluster Replication”.
The log_name, start_pos, and
end_pos columns were added in MySQL 5.1.18.
Important
If you are using MySQL Cluster replication, see Section 5.2, “MySQL Cluster 5.1 and MySQL Cluster NDB 6.x/7.x Upgrade and Downgrade Compatibility” before upgrading to MySQL 5.1.18 or later from an earlier version.
The ndb_binlog_index and
ndb_apply_status tables are created in the
mysql database because they should not be
replicated. No user intervention is normally required to create or
maintain either of them. Both the
ndb_binlog_index and the
ndb_apply_status tables are maintained by the
NDB injector thread. This keeps the
master mysqld process updated to changes
performed by the NDB storage engine.
The NDB binlog injector
thread receives events directly from the
NDB storage engine. The
NDB injector is responsible for
capturing all the data events within the cluster, and ensures that
all events which change, insert, or delete data are recorded in
the ndb_binlog_index table. The slave I/O
thread transfers the events from the master's binary log to the
slave's relay log.
However, it is advisable to check for the existence and integrity
of these tables as an initial step in preparing a MySQL Cluster
for replication. It is possible to view event data recorded in the
binary log by querying the
mysql.ndb_binlog_index table directly on the
master. This can be also be accomplished using the
SHOW BINLOG EVENTS statement on
either the replication master or slave MySQL servers. (See
SHOW BINLOG EVENTS Syntax.)
You can also obtain useful information from the output of
SHOW ENGINE NDB
STATUS.
The ndb_schema table is used to track schema
changes made to NDB tables. It is
defined as shown here:
CREATE TABLE ndb_schema (
`db` VARBINARY(63) NOT NULL,
`name` VARBINARY(63) NOT NULL,
`slock` BINARY(32) NOT NULL,
`query` BLOB NOT NULL,
`node_id` INT UNSIGNED NOT NULL,
`epoch` BIGINT UNSIGNED NOT NULL,
`id` INT UNSIGNED NOT NULL,
`version` INT UNSIGNED NOT NULL,
`type` INT UNSIGNED NOT NULL,
PRIMARY KEY USING HASH (db,name)
) ENGINE=NDB DEFAULT CHARSET=latin1;
Unlike the two tables previously mentioned in this section, the
ndb_schema table is not visible either to MySQL
SHOW statements, or in any
INFORMATION_SCHEMA tables; however, it can be
seen in the output of ndb_show_tables, as shown
here:
shell> ndb_show_tables -t 2
id type state logging database schema name
4 UserTable Online Yes mysql def ndb_apply_status
5 UserTable Online Yes ndbworld def City
6 UserTable Online Yes ndbworld def Country
3 UserTable Online Yes mysql def NDB$BLOB_2_3
7 UserTable Online Yes ndbworld def CountryLanguage
2 UserTable Online Yes mysql def ndb_schema
NDBT_ProgramExit: 0 - OK
It is also possible to SELECT from
this table in mysql and other MySQL client
applications, as shown here:
mysql> SELECT * FROM mysql.ndb_schema WHERE name='City' \G
*************************** 1. row ***************************
db: ndbworld
name: City
slock:
query: alter table City engine=ndb
node_id: 4
epoch: 0
id: 0
version: 0
type: 7
1 row in set (0.00 sec)
This can sometimes be useful when debugging applications.
Note
When performing schema changes on
NDB tables, applications should
wait until the ALTER TABLE
statement has returned in the MySQL client connection that
issued the statement before attempting to use the updated
definition of the table.
The ndb_schema table was added in MySQL 5.1.8.
Beginning with MySQL 5.1.14, if either of the
ndb_apply_status or
ndb_schema tables does not exist on the slave,
it is created by ndb_restore. (Bug#14612)
Conflict resolution for MySQL Cluster Replication requires the
presence of an additional mysql.ndb_replication
table. Currently, this table must be created manually. For
details, see
Section 9.11, “MySQL Cluster Replication Conflict Resolution”.
Preparing the MySQL Cluster for replication consists of the following steps:
Check all MySQL servers for version compatibility (see Section 9.2, “MySQL Cluster Replication — Assumptions and General Requirements”).
Create a slave account on the master Cluster with the appropriate privileges:
mysql
M>GRANT REPLICATION SLAVE->ON *.* TO '->slave_user'@'slave_host'IDENTIFIED BY 'slave_password';In the previous statement,
slave_useris the slave account user name,slave_hostis the host name or IP address of the replication slave, andslave_passwordis the password to assign to this account.For example, to create a slave user account with the name “
myslave,” logging in from the host named “rep-slave,” and using the password “53cr37,” use the followingGRANTstatement:mysql
M>GRANT REPLICATION SLAVE->ON *.* TO 'myslave'@'rep-slave'->IDENTIFIED BY '53cr37';For security reasons, it is preferable to use a unique user account — not employed for any other purpose — for the replication slave account.
Configure the slave to use the master. Using the MySQL Monitor, this can be accomplished with the
CHANGE MASTER TOstatement:mysql
S>CHANGE MASTER TO->MASTER_HOST='->master_host',MASTER_PORT=->master_port,MASTER_USER='->slave_user',MASTER_PASSWORD='slave_password';In the previous statement,
master_hostis the host name or IP address of the replication master,master_portis the port for the slave to use for connecting to the master,slave_useris the user name set up for the slave on the master, andslave_passwordis the password set for that user account in the previous step.For example, to tell the slave to replicate from the MySQL server whose host name is “
rep-master,” using the replication slave account created in the previous step, use the following statement:mysql
S>CHANGE MASTER TO->MASTER_HOST='rep-master'->MASTER_PORT=3306,->MASTER_USER='myslave'->MASTER_PASSWORD='53cr37';For a complete list of clauses that can be used with this statement, see
CHANGE MASTER TOSyntax.You can also configure the slave to use the master by setting the corresponding startup options in the slave server's
my.cnffile. To configure the slave in the same way as the preceding exampleCHANGE MASTER TOstatement, the following information would need to be included in the slave'smy.cnffile:[mysqld] master-host=rep-master master-port=3306 master-user=myslave master-password=53cr37
For additional options that can be set in
my.cnffor replication slaves, see Replication and Binary Logging Options and Variables.Note
To provide replication backup capability, you will also need to add an
ndb-connectstringoption to the slave'smy.cnffile prior to starting the replication process. See Section 9.9, “MySQL Cluster Backups With MySQL Cluster Replication”, for details.If the master cluster is already in use, you can create a backup of the master and load this onto the slave to cut down on the amount of time required for the slave to synchronize itself with the master. If the slave is also running MySQL Cluster, this can be accomplished using the backup and restore procedure described in Section 9.9, “MySQL Cluster Backups With MySQL Cluster Replication”.
ndb-connectstring=
management_host[:port]In the event that you are not using MySQL Cluster on the replication slave, you can create a backup with this command on the replication master:
shell
M>mysqldump --master-data=1Then import the resulting data dump onto the slave by copying the dump file over to the slave. After this, you can use the mysql client to import the data from the dumpfile into the slave database as shown here, where
dump_fileis the name of the file that was generated using mysqldump on the master, anddb_nameis the name of the database to be replicated:shell
S>mysql -u root -pdb_name<dump_fileFor a complete list of options to use with mysqldump, see mysqldump.
Note
If you copy the data to the slave in this fashion, you should make sure that the slave is started with the
--skip-slave-startoption on the command line, or else includeskip-slave-startin the slave'smy.cnffile to keep it from trying to connect to the master to begin replicating before all the data has been loaded. Once the data loading has completed, follow the additional steps outlined in the next two sections.Ensure that each MySQL server acting as a replication master is configured with a unique server ID, and with binary logging enabled, using the row format. (See Replication Formats.) These options can be set either in the master server's
my.cnffile, or on the command line when starting the master mysqld process. See Section 9.6, “Starting MySQL Cluster Replication (Single Replication Channel)”, for information regarding the latter option.
This section outlines the procedure for starting MySQL CLuster replication using a single replication channel.
Start the MySQL replication master server by issuing this command:
shell
M>mysqld --ndbcluster --server-id=id\--log-bin --binlog-format=ROW &In the previous statement,
idis this server's unique ID (see Section 9.2, “MySQL Cluster Replication — Assumptions and General Requirements”). This starts the server's mysqld process with binary logging enabled using the proper logging format.Note
You can also start the master with
--binlog-format=MIXED, in which case row-based replication is used automatically when replicating between clusters.Start the MySQL replication slave server as shown here:
shell
S>mysqld --ndbcluster --server-id=id&In the previous statement,
idis the slave server's unique ID. It is not necessary to enable logging on the replication slave.Note
You should use the
--skip-slave-startoption with this command or else you should includeskip-slave-startin the slave server'smy.cnffile, unless you want replication to begin immediately. With the use of this option, the start of replication is delayed until the appropriateSTART SLAVEstatement has been issued, as explained in Step 4 below.It is necessary to synchronize the slave server with the master server's replication binlog. If binary logging has not previously been running on the master, run the following statement on the slave:
mysql
S>CHANGE MASTER TO->MASTER_LOG_FILE='',->MASTER_LOG_POS=4;This instructs the slave to begin reading the master's binary log from the log's starting point. Otherwise — that is, if you are loading data from the master using a backup — see Section 9.8, “Implementing Failover with MySQL Cluster Replication”, for information on how to obtain the correct values to use for
MASTER_LOG_FILEandMASTER_LOG_POSin such cases.Finally, you must instruct the slave to begin applying replication by issuing this command from the mysql client on the replication slave:
mysql
S>START SLAVE;This also initiates the transmission of replication data from the master to the slave.
It is also possible to use two replication channels, in a manner simliar to the procedure described in the next section; the differences between this and using a single replication channel are covered in Section 9.7, “Using Two Replication Channels for MySQL Cluster Replication”.
Beginning with MySQL Cluster NDB 6.2.3, it is possible to improve
cluster replication performance by enabling batched
updates. This can be accomplished by starting slave
mysqld processes with the
--slave-allow-batching option. Normally, updates
are applied as soon as they are received. However, the use of
batching causes updates to be applied in 32 KB batches, which can
result in higher throughput and less CPU usage, particularly where
individual updates are relatively small.
Note
Slave batching works on a per-epoch basis; updates belonging to more than one transaction can be sent as part of the same batch.
All outstanding updates are applied when the end of an epoch is reached, even if the updates total less than 32 KB.
Batching can be turned on and off at runtime. To activate it at runtime, you can use either of these two statements:
SET GLOBAL slave_allow_batching = 1; SET GLOBAL slave_allow_batching = ON;
If a particular batch causes problems (such as a statement whose effects do not appear to be replicated correctly), slave batching can be deactivated using either of the following statements:
SET GLOBAL slave_allow_batching = 0; SET GLOBAL slave_allow_batching = OFF;
You can check whether slave batching is currently being used by
means of an appropriate SHOW
VARIABLES statement, like this one:
mysql> SHOW VARIABLES LIKE 'slave%';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| slave_allow_batching | ON |
| slave_compressed_protocol | OFF |
| slave_load_tmpdir | /tmp |
| slave_net_timeout | 3600 |
| slave_skip_errors | OFF |
| slave_transaction_retries | 10 |
+---------------------------+-------+
6 rows in set (0.00 sec)
In a more complete example scenario, we envision two replication channels to provide redundancy and thereby guard against possible failure of a single replication channel. This requires a total of four replication servers, two masters for the master cluster and two slave servers for the slave cluster. For purposes of the discussion that follows, we assume that unique identifiers are assigned as shown here:
| Server ID | Description |
| 1 | Master - primary replication channel (M) |
| 2 | Master - secondary replication channel (M') |
| 3 | Slave - primary replication channel (S) |
| 4 | Slave - secondary replication channel (S') |
Setting up replication with two channels is not radically
different from setting up a single replication channel. First, the
mysqld processes for the primary and secondary
replication masters must be started, followed by those for the
primary and secondary slaves. Then the replication processes may
be initiated by issuing the START
SLAVE statement on each of the slaves. The commands and
the order in which they need to be issued are shown here:
Start the primary replication master:
shell
M>mysqld --ndbcluster --server-id=1 \--log-bin --binlog-format=row &Start the secondary replication master:
shell
M'>mysqld --ndbcluster --server-id=2 \--log-bin --binlog-format=row &Start the primary replication slave server:
shell
S>mysqld --ndbcluster --server-id=3 \--skip-slave-start &Start the secondary replication slave:
shell
S'>mysqld --ndbcluster --server-id=4 \--skip-slave-start &Finally, initiate replication on the primary channel by executing the
START SLAVEstatement on the primary slave as shown here:mysql
S>START SLAVE;Warning
Only the primary channel is to be started at this point. The secondary replication channel is to be started only in the event that the primary replication channel fails, as described in Section 9.8, “Implementing Failover with MySQL Cluster Replication”. Running multiple replication channels simultaneously can result in unwanted duplicate records being created on the replication slaves.
As mentioned previously, it is not necessary to enable binary logging on replication slaves.
In the event that the primary Cluster replication process fails, it is possible to switch over to the secondary replication channel. The following procedure describes the steps required to accomplish this.
Obtain the time of the most recent global checkpoint (GCP). That is, you need to determine the most recent epoch from the
ndb_apply_statustable on the slave cluster, which can be found using the following query:mysql
S'>SELECT @latest:=MAX(epoch)->FROM mysql.ndb_apply_status;Using the information obtained from the query shown in Step 1, obtain the corresponding records from the
ndb_binlog_indextable on the master cluster as shown here:mysql
M'>SELECT->@file:=SUBSTRING_INDEX(File, '/', -1),->@pos:=Position->FROM mysql.ndb_binlog_index->WHERE epoch > @latest->ORDER BY epoch ASC LIMIT 1;These are the records saved on the master since the failure of the primary replication channel. We have employed a user variable
@latesthere to represent the value obtained in Step 1. Of course, it is not possible for one mysqld instance to access user variables set on another server instance directly. These values must be “plugged in” to the second query manually or in application code.Now it is possible to synchronize the secondary channel by running the following query on the secondary slave server:
mysql
S'>CHANGE MASTER TO->MASTER_LOG_FILE='@file',->MASTER_LOG_POS=@pos;Again we have employed user variables (in this case
@fileand@pos) to represent the values obtained in Step 2 and applied in Step 3; in practice these values must be inserted manually or using application code that can access both of the servers involved.Note
@fileis a string value such as'/var/log/mysql/replication-master-bin.00001', and so must be quoted when used in SQL or application code. However, the value represented by@posmust not be quoted. Although MySQL normally attempts to convert strings to numbers, this case is an exception.You can now initiate replication on the secondary channel by issuing the appropriate command on the secondary slave mysqld:
mysql
S'>START SLAVE;
Once the secondary replication channel is active, you can investigate the failure of the primary and effect repairs. The precise actions required to do this will depend upon the reasons for which the primary channel failed.
Warning
The secondary replication channel is to be started only if and when the primary replication channel has failed. Running multiple replication channels simultaneously can result in unwanted duplicate records being created on the replication slaves.
If the failure is limited to a single server, it should (in
theory) be possible to replicate from M
to S', or from
M' to S;
however, this has not yet been tested.
This section discusses making backups and restoring from them using MySQL Cluster replication. We assume that the replication servers have already been configured as covered previously (see Section 9.5, “Preparing the MySQL Cluster for Replication”, and the sections immediately following). This having been done, the procedure for making a backup and then restoring from it is as follows:
There are two different methods by which the backup may be started.
Method A. This method requires that the cluster backup process was previously enabled on the master server, prior to starting the replication process. This can be done by including the following line in a
[mysql_cluster]section in themy.cnf file, wheremanagement_hostis the IP address or host name of theNDBmanagement server for the master cluster, andportis the management server's port number:ndb-connectstring=
management_host[:port]Note
The port number needs to be specified only if the default port (1186) is not being used. See Section 2.3, “MySQL Cluster Multi-Computer Configuration”, for more information about ports and port allocation in MySQL Cluster.
In this case, the backup can be started by executing this statement on the replication master:
shell
M>ndb_mgm -e "START BACKUP"Method B. If the
my.cnffile does not specify where to find the management host, you can start the backup process by passing this information to theNDBmanagement client as part of theSTART BACKUPcommand. This can be done as shown here, wheremanagement_hostandportare the host name and port number of the management server:shell
M>ndb_mgmmanagement_host:port-e "START BACKUP"In our scenario as outlined earlier (see Section 9.5, “Preparing the MySQL Cluster for Replication”), this would be executed as follows:
shell
M>ndb_mgm rep-master:1186 -e "START BACKUP"
Copy the cluster backup files to the slave that is being brought on line. Each system running an ndbd process for the master cluster will have cluster backup files located on it, and all of these files must be copied to the slave to ensure a successful restore. The backup files can be copied into any directory on the computer where the slave management host resides, so long as the MySQL and NDB binaries have read permissions in that directory. In this case, we will assume that these files have been copied into the directory
/var/BACKUPS/BACKUP-1.It is not necessary that the slave cluster have the same number of ndbd processes (data nodes) as the master; however, it is highly recommended this number be the same. It is necessary that the slave be started with the
--skip-slave-startoption, to prevent premature startup of the replication process.Create any databases on the slave cluster that are present on the master cluster that are to be replicated to the slave.
Important
A
CREATE DATABASE(orCREATE SCHEMA) statement corresponding to each database to be replicated must be executed on each SQL node in the slave cluster.Reset the slave cluster using this statement in the MySQL Monitor:
mysql
S>RESET SLAVE;It is important to make sure that the slave's
apply_statustable does not contain any records prior to running the restore process. You can accomplish this by running this SQL statement on the slave:mysql
S>DELETE FROM mysql.ndb_apply_status;You can now start the cluster restoration process on the replication slave using the ndb_restore command for each backup file in turn. For the first of these, it is necessary to include the
-moption to restore the cluster metadata:shell
S>ndb_restore -cslave_host:port-nnode-id\-bbackup-id-m -rdirdiris the path to the directory where the backup files have been placed on the replication slave. For the ndb_restore commands corresponding to the remaining backup files, the-moption should not be used.For restoring from a master cluster with four data nodes (as shown in the figure in Chapter 9, MySQL Cluster Replication) where the backup files have been copied to the directory
/var/BACKUPS/BACKUP-1, the proper sequence of commands to be executed on the slave might look like this:shell
S>ndb_restore -c rep-slave:1186 -n 2 -b 1 -m \-r ./var/BACKUPS/BACKUP-1shellS>ndb_restore -c rep-slave:1186 -n 3 -b 1 \-r ./var/BACKUPS/BACKUP-1shellS>ndb_restore -c rep-slave:1186 -n 4 -b 1 \-r ./var/BACKUPS/BACKUP-1shellS>ndb_restore -c rep-slave:1186 -n 5 -b 1 -e \-r ./var/BACKUPS/BACKUP-1Important
The
-e(or--restore-epoch) option in the final invocation of ndb_restore in this example is required in order that the epoch is written to the slavemysql.ndb_apply_status. Without this information, the slave will not be able to synchronize properly with the master. (See Section 6.17, “ndb_restore — Restore a MySQL Cluster Backup”.)Now you need to obtain the most recent epoch from the
ndb_apply_statustable on the slave (as discussed in Section 9.8, “Implementing Failover with MySQL Cluster Replication”):mysql
S>SELECT @latest:=MAX(epoch)FROM mysql.ndb_apply_status;Using
@latestas the epoch value obtained in the previous step, you can obtain the correct starting position@posin the correct binary log file@filefrom the master'smysql.ndb_binlog_indextable using the query shown here:mysql
M>SELECT->@file:=SUBSTRING_INDEX(File, '/', -1),->@pos:=Position->FROM mysql.ndb_binlog_index->WHERE epoch > @latest->ORDER BY epoch ASC LIMIT 1;In the event that there is currently no replication traffic, you can get this information by running
SHOW MASTER STATUSon the master and using the value in thePositioncolumn for the file whose name has the suffix with the greatest value for all files shown in theFilecolumn. However, in this case, you must determine this and supply it in the next step manually or by parsing the output with a script.Using the values obtained in the previous step, you can now issue the appropriate
CHANGE MASTER TOstatement in the slave's mysql client:mysql
S>CHANGE MASTER TO->MASTER_LOG_FILE='@file',->MASTER_LOG_POS=@pos;Now that the slave “knows” from what point in which
binlogfile to start reading data from the master, you can cause the slave to begin replicating with this standard MySQL statement:mysql
S>START SLAVE;
To perform a backup and restore on a second replication channel, it is necessary only to repeat these steps, substituting the host names and IDs of the secondary master and slave for those of the primary master and slave replication servers where appropriate, and running the preceding statements on them.
For additional information on performing Cluster backups and restoring Cluster from backups, see Section 7.3, “Online Backup of MySQL Cluster”.
It is possible to automate much of the process described in the
previous section (see
Section 9.9, “MySQL Cluster Backups With MySQL Cluster Replication”). The
following Perl script reset-slave.pl serves
as an example of how you can do this.
#!/user/bin/perl -w
# file: reset-slave.pl
# Copyright ©2005 MySQL AB
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to:
# Free Software Foundation, Inc.
# 59 Temple Place, Suite 330
# Boston, MA 02111-1307 USA
#
# Version 1.1
######################## Includes ###############################
use DBI;
######################## Globals ################################
my $m_host='';
my $m_port='';
my $m_user='';
my $m_pass='';
my $s_host='';
my $s_port='';
my $s_user='';
my $s_pass='';
my $dbhM='';
my $dbhS='';
####################### Sub Prototypes ##########################
sub CollectCommandPromptInfo;
sub ConnectToDatabases;
sub DisconnectFromDatabases;
sub GetSlaveEpoch;
sub GetMasterInfo;
sub UpdateSlave;
######################## Program Main ###########################
CollectCommandPromptInfo;
ConnectToDatabases;
GetSlaveEpoch;
GetMasterInfo;
UpdateSlave;
DisconnectFromDatabases;
################## Collect Command Prompt Info ##################
sub CollectCommandPromptInfo
{
### Check that user has supplied correct number of command line args
die "Usage:\n
reset-slave >master MySQL host< >master MySQL port< \n
>master user< >master pass< >slave MySQL host< \n
>slave MySQL port< >slave user< >slave pass< \n
All 8 arguments must be passed. Use BLANK for NULL passwords\n"
unless @ARGV == 8;
$m_host = $ARGV[0];
$m_port = $ARGV[1];
$m_user = $ARGV[2];
$m_pass = $ARGV[3];
$s_host = $ARGV[4];
$s_port = $ARGV[5];
$s_user = $ARGV[6];
$s_pass = $ARGV[7];
if ($m_pass eq "BLANK") { $m_pass = '';}
if ($s_pass eq "BLANK") { $s_pass = '';}
}
############### Make connections to both databases #############
sub ConnectToDatabases
{
### Connect to both master and slave cluster databases
### Connect to master
$dbhM
= DBI->connect(
"dbi:mysql:database=mysql;host=$m_host;port=$m_port",
"$m_user", "$m_pass")
or die "Can't connect to Master Cluster MySQL process!
Error: $DBI::errstr\n";
### Connect to slave
$dbhS
= DBI->connect(
"dbi:mysql:database=mysql;host=$s_host",
"$s_user", "$s_pass")
or die "Can't connect to Slave Cluster MySQL process!
Error: $DBI::errstr\n";
}
################ Disconnect from both databases ################
sub DisconnectFromDatabases
{
### Disconnect from master
$dbhM->disconnect
or warn " Disconnection failed: $DBI::errstr\n";
### Disconnect from slave
$dbhS->disconnect
or warn " Disconnection failed: $DBI::errstr\n";
}
###################### Find the last good GCI ##################
sub GetSlaveEpoch
{
$sth = $dbhS->prepare("SELECT MAX(epoch)
FROM mysql.ndb_apply_status;")
or die "Error while preparing to select epoch from slave: ",
$dbhS->errstr;
$sth->execute
or die "Selecting epoch from slave error: ", $sth->errstr;
$sth->bind_col (1, \$epoch);
$sth->fetch;
print "\tSlave Epoch = $epoch\n";
$sth->finish;
}
####### Find the position of the last GCI in the binlog ########
sub GetMasterInfo
{
$sth = $dbhM->prepare("SELECT
SUBSTRING_INDEX(File, '/', -1), Position
FROM mysql.ndb_binlog_index
WHERE epoch > $epoch
ORDER BY epoch ASC LIMIT 1;")
or die "Prepare to select from master error: ", $dbhM->errstr;
$sth->execute
or die "Selecting from master error: ", $sth->errstr;
$sth->bind_col (1, \$binlog);
$sth->bind_col (2, \$binpos);
$sth->fetch;
print "\tMaster bin log = $binlog\n";
print "\tMaster Bin Log position = $binpos\n";
$sth->finish;
}
########## Set the slave to process from that location #########
sub UpdateSlave
{
$sth = $dbhS->prepare("CHANGE MASTER TO
MASTER_LOG_FILE='$binlog',
MASTER_LOG_POS=$binpos;")
or die "Prepare to CHANGE MASTER error: ", $dbhS->errstr;
$sth->execute
or die "CHANGE MASTER on slave error: ", $sth->errstr;
$sth->finish;
print "\tSlave has been updated. You may now start the slave.\n";
}
# end reset-slave.pl
Beginning with MySQL 5.1.18, it is possible to use MySQL Cluster in multi-master replication, including circular replication between a number of MySQL Clusters.
Note
Prior to MySQL 5.1.18, multi-master replication including circular replication was not supported with MySQL Cluster replication. This was because log events created in a particular MySQL Cluster were wrongly tagged with the server ID of the master rather than the server ID of the originating server.
Circular replication example. In the next few paragraphs we consider the example of a replication setup involving three MySQL Clusters numbered 1, 2, and 3, in which Cluster 1 acts as the replication master for Cluster 2, Cluster 2 acts as the master for Cluster 3, and Cluster 3 acts as the master for Cluster 1. Each cluster has two SQL nodes, with SQL nodes A and B belonging to Cluster 1, SQL nodes C and D belonging to Cluster 2, and SQL nodes E and F belonging to Cluster 3.
Circular replication using these clusters is supported as long as:
The SQL nodes on all masters and slaves are the same
All SQL nodes acting as replication masters and slaves are started using the
--log-slave-updatesoption
This type of circular replication setup is shown in the following diagram:

In this scenario, SQL node A in Cluster 1 replicates to SQL node C in Cluster 2; SQL node C replicates to SQL node E in Cluster 3; SQL node E replicates to SQL node A. In other words, the replication line (indicated by the red arrows in the diagram) directly connects all SQL nodes used as replication masters and slaves.
It is also possible to set up circular replication in such a way that not all master SQL nodes are also slaves, as shown here:

In this case, different SQL nodes in each cluster are used as
replication masters and slaves. However, you must
not start any of the SQL nodes using
--log-slave-updates (see the
description of
this option for more information). This type of circular
replication scheme for MySQL Cluster, in which the line of
replication (again indicated by the red arrows in the diagram) is
discontinuous, should be possible, but it should be noted that it
has not yet been thoroughly tested and must therefore still be
considered experimental.
Important
Beginning with MySQL 5.1.24, you should execute the following statement before starting circular replication:
mysql> SET GLOBAL SLAVE_EXEC_MODE = 'IDEMPOTENT';
This is necessary to suppress duplicate-key and other errors
that otherwise break circular replication in MySQL Cluster.
IDEMPOTENT mode is also required for
multi-master replication when using MySQL Cluster. (Bug#31609)
See slave_exec_mode, for more
information.
Using NDB-native backup and restore to initialize a slave MySQL Cluster.
When setting up circular replication, it is possible to
initialize the slave cluster by using the management client
BACKUP command on one MySQL Cluster to create
a backup and then applying this backup on another MySQL Cluster
using ndb_restore. However, this does not
automatically create binary logs on the second MySQL
Cluster's SQL node acting as the replication slave. In
order to cause the binary logs to be created, you must issue a
SHOW TABLES statement on that SQL
node; this should be done prior to running
START SLAVE.
This is a known issue which we intend to address in a future release.
Multi-master failover example. In this section, we discuss failover in a multi-master MySQL Cluster replication setup with three MySQL Clusters having server IDs 1, 2, and 3. In this scenario, Cluster 1 replicates to Clusters 2 and 3; Cluster 2 also replicates to Cluster 3. This relationship is shown here:

In other words, data replicates from Cluster 1 to Cluster 3 via 2 different routes: directly, and by way of Cluster 2.
Not all MySQL servers taking part in multi-master replication must act as both master and slave, and a given MySQL Cluster might use different SQL nodes for diffferent replication channels. Such a case is shown here:

MySQL servers acting as replication slaves must be run with the
--log-slave-updates option. Which
mysqld processes require this option is also
shown in the preceding diagram.
Note
Using the --log-slave-updates option has
no effect on servers not being run as replication slaves.
The need for failover arises when one of the replicating clusters goes down. In this example, we consider the case where Cluster 1 is lost to service, and so Cluster 3 loses 2 sources of updates from Cluster 1. Because replication between MySQL Clusters is asynchronous, there is no guarantee that Cluster 3's updates originating directly from Cluster 1 are more recent than those received via Cluster 2. You can handle this by ensuring that Cluster 3 catches up to Cluster 2 with regard to updates from Cluster 1. In terms of MySQL servers, this means that you need to replicate any outstanding updates from MySQL server C to server F.
On server C, perform the following queries:
mysqlC> SELECT @latest:=MAX(epoch)
-> FROM mysql.ndb_apply_status
-> WHERE server_id=1;
mysqlC> SELECT
-> @file:=SUBSTRING_INDEX(File, '/', -1),
-> @pos:=Position
-> FROM mysql.ndb_binlog_index
-> WHERE orig_epoch >= @latest
-> AND orig_server_id = 1
-> ORDER BY epoch ASC LIMIT 1;
Copy over the values for @file and
@pos manually from server C to server F
(or have your application perform the equivalent). Then, on server
F, execute the following CHANGE MASTER
TO statement:
mysqlF> CHANGE MASTER TO
-> MASTER_HOST = 'serverC'
-> MASTER_LOG_FILE='@file',
-> MASTER_LOG_POS=@pos;
Once this has been done, you can issue a
START SLAVE statement on MySQL
server F, and any missing updates originating from server B will
be replicated to server F.
When using a replication setup involving multiple masters
(including circular replication), it is possible that different
masters may try to update the same row on the slave with different
data. Conflict resolution in MySQL Cluster Replication provides a
means of resolving such conflicts by allowing a user defined
resolution column to be used to determine whether or not an update
to the row on a given master should be applied on the slave. (This
column is sometimes referred to as a “timestamp”
column, even though this column' type cannot be
TIMESTAMP, as explained later in
this section.) Different methods can be used to compare resolution
column values on the slave when conflicts occur, as explained
later in this section; the method used can be set on a per-table
basis.
Important
Conflict resolution as described in this section is always applied on a row-by-row basis rather than a transactional basis. In addition, it is the application's responsibility to ensure that the resolution column is correctly populated with relevant values, so that the resolution function can make the appropriate choice when determining whether to apply an update.
Requirements. Preparations for conflict resolution must be made on both the master and the slave:
On the master writing the binlogs, you must determine which columns are sent (all columns or only those that have been updated). This is done for the MySQL Server as a whole by applying the mysqld startup option
-ândb-log-updated-only(described later in this section) or on a per-table basis by entries in themysql.ndb_replicationtable.On the slave, you must determine which type of conflict resolution to apply (“latest timestamp wins”, “same timestamp wins”, or none). This is done using the
mysql.ndb_replicationsystem table, on a per-table basis.
If only some but not all columns are sent, then the master and slave can diverge.
Note
We refer to the column used for determining updates as a
“timestamp” column, but the data type of this
column is never TIMESTAMP;
rather, its data type should be
INT
(INTEGER) or
BIGINT. This column should be
UNSIGNED and NOT NULL.
Master column control.
We can see update operations in terms of “before”
and “after” images — that is, the states of
the table before and after the update is applied. Normally, when
updating a table with a primary key, the “before”
image is not of great interest; however, when we need to
determine on a per-update basis whether or not to use the
updated values on a replication slave, we need to make sure that
both images are written to the master's binary log. This is
done with the
--ndb-log-update-as-write option
for mysqld, as described later in this
section.
Important
Whether logging of complete rows or of updated columns only is done is decided when the MySQL server is started, and cannot be changed online; you must either restart mysqld, or start a new mysqld instance with different logging options.
Logging full or partial rows (--ndb-log-updated-only
option).
For purposes of conflict resolution, there are two basic methods
of logging rows, as determined by the setting of the
--ndb-log-updated-only option for
mysqld:
Log complete rows
Log only column data that has been updated — that is, column data whose value has been set, regardless of whether or not this value was actually changed.
It is more efficient to log updated columns only; however, if
you need to log full rows, you can do so by setting
--ndb-log-updated-only to 0
or OFF.
Logging changed data as updates
(--ndb-log-update-as-write
option).
Either of these logging methods can be configured to be done
with or without the “before” image as determined by
the setting of another MySQL Server option
--ndb-log-update-as-write.
Because conflict resolution is done in the MySQL Server's update
handler, it is necessary to control logging on the master such
that updates are updates and not writes; that is, such that
updates are treated as changes in existing rows rather than the
writing of new rows (even though these replace existing rows).
This option is turned on by default; to turn it off, start the
server with --ndb-log-update-as-write=0 or
--ndb-log-update-as-write=OFF.
Conflict resolution control.
Conflict resolution is usually enabled on the server where
conflicts can occur. Like logging method selection, it is
enabled by entries in the
mysql.ndb_replication table.
The ndb_replication system table.
To enable conflict resolution, it is necessary to create an
ndb_replication table in the
mysql system database on the master, the
slave, or both, depending on the conflict resolution type and
method to be employed. This table is used to control logging and
conflict resolution functions on a per-table basis, and has one
row per table involved in replication.
ndb_replication is created and filled with
control information on the server where the conflict is to be
resolved. In a simple master-slave setup where data can also be
changed locally on the slave this will typically be the slave.
In a more complex master-master (2-way) replication schema this
will usually be all of the masters involved. Each row in
mysql.ndb_replication corresponds to a table
being replicated, and specifies how to log and resolve conflicts
(that is, which conflict resolution function, if any, to use)
for that table. The definition of the
mysql.ndb_replication table is shown here:
CREATE TABLE mysql.ndb_replication (
db VARBINARY(63),
table_name VARBINARY(63),
server_id INT UNSIGNED,
binlog_type INT UNSIGNED,
conflict_fn VARBINARY(128),
PRIMARY KEY USING HASH (db, table_name, server_id)
) ENGINE=NDB
PARTITION BY KEY(db,table_name);
The columns in this table are described in the following list:
db. The name of the database containing the table to be replicated.table_name. The name of the table to be replicated.server_id. The unique server ID of the MySQL instance (SQL node) where the table resides.binlog_type. The type of binary logging to be employed. This is determined as shown in the following table:Value Internal Value Description 0 NBT_DEFAULTUse server default 1 NBT_NO_LOGGINGDo not log this table in the binary log 2 NBT_UPDATED_ONLYOnly updated attributes are logged 3 NBT_FULLLog full row, even if not updated (MySQL server default behavior) 4 NBT_USE_UPDATE(For generating NBT_UPDATED_ONLY_USE_UPDATEandNBT_FULL_USE_UPDATEvalues only — not intended for separate use)5 [Not used] --- 6 NBT_UPDATED_ONLY_USE_UPDATE(equal toNBT_UPDATED_ONLY | NBT_USE_UPDATE)Use updated attributes, even if values are unchanged 7 NBT_FULL_USE_UPDATE(equal toNBT_FULL | NBT_USE_UPDATE)Use full row, even if values are unchanged conflict_fn. The conflict resolution function to be applied. This function must be specified as one of the following:NDB$MAX(). If the “timestamp” column value for a given row coming from the master is higher than that on the slave, it is applied; otherwise it is not applied on the slave. This is illustrated by the following pseudocode:column_nameif (
master_new_column_value>slave_current_column_value) perform_update();This function can be used for “greatest timestamp wins” conflict resolution. This type of conflict resolution ensures that, in the event of a conflict, the version of the row that was most recently updated is the version that persists.
Important
The column value from the master's “after” image is used by this function.
This conflict resolution function is available beginning with MySQL Cluster NDB 6.3.0.
NDB$OLD(). If the value ofcolumn_namecolumn_nameis the same on both the master and the slave, then the update is applied; otherwise, the update is not applied on the slave and an exception is written to the log. This is illustrated by the following pseudocode:if (
master_old_column_value==slave_current_column_value) perform_update(); else log_exception();This function can be used for “same value wins” conflict resolution. This type of conflict resolution ensures that updates are not applied on the slave from the wrong master.
Important
The column value from the master's “before” image is used by this function.
This conflict resolution function is available beginning with MySQL Cluster NDB 6.3.4.
NULL: Indicates that conflict resolution is not to be used for the corresponding table
.
Status information.
Beginning with MySQL Cluster NDB 6.3.3, a server status variable
Ndb_conflict_fn_max provides a
count of the number of times that a row was not applied on the
current SQL node due to “greatest timestamp wins”
conflict resolution since the last time that
mysqld was started.
Beginning with MySQL Cluster NDB 6.3.4, the number of times that a
row was not applied as the result of “same timestamp
wins” conflict resolution on a given
mysqld since the last time it was restarted is
given by the global status variable
Ndb_conflict_fn_old. In addition
to incrementing
Ndb_conflict_fn_old, the primary
key of the row that was not used is inserted into an
exceptions table, as explained later in
this section.
Additional requirements for “Same timestamp wins” conflict
resolution.
To use the NDB$OLD() conflict resolution
function, it is also necessary to create an exceptions table
corresponding to each NDB table for
which this type of conflict resolution is to be employed. The
name of this table is that of the table for which “same
timestamp wins” conflict resolution is to be applied,
with the string $EX appended. (For example,
if the name of the original table is mytable,
the name of the corresponding exception table name should be
mytable$EX.) This table is created as
follows:
CREATE TABLEoriginal_table$EX ( server_id INT UNSIGNED, master_server_id INT UNSIGNED, master_epoch BIGINT UNSIGNED, count INT UNSIGNED,original_table_pk_columns, [additional_columns,] PRIMARY KEY(server_id, master_server_id, master_epoch, count) ) ENGINE=NDB;
The first four columns are required. Following these columns, the columns making up the original table's primary key should be copied in the order in which they are used to define the primary key of the original table.
Note
The names of the first four columns and the columns matching
the original table's primary key columns are not critical;
however, we suggest for reasons of clarity and consistency,
that you use the names shown here for the
server_id,
master_server_id,
master_epoch, and
count columns, and that you use the same
names as in the original table for the columns matching
those in the original table's primary key.
The data types for the columns duplicating the primary key columns of the original table should be the same as for (or larger than) the original columns.
Additional columns may optionally be defined following these
columns, but not before any of them; any such extra columns
cannot be NOT NULL. The exception
table's primary key must be defined as shown. The exception
table must use the NDB storage
engine. An example of use for NDB$OLD() and
an exception table is given later in this section.
Important
The mysql.ndb_replication table is read when
a data table is set up for replication, so the row corresponding
to a table to be replicated must be inserted into
mysql.ndb_replication
before the table to be replicated is
created.
Examples. The following examples assume that you have already a working MySQL Cluster replication setup, as described in Section 9.5, “Preparing the MySQL Cluster for Replication”, and Section 9.6, “Starting MySQL Cluster Replication (Single Replication Channel)”.
NDB$MAX()example. Suppose you wish to enable “greatest timestamp wins” conflict resolution on tabletest.t1, using columnmycolas the “timestamp”. This can be done using the following steps:Make sure that you have started the master mysqld with
-ândb-log-update-as-write=OFF.On the master, perform this
INSERTstatement:INSERT INTO mysql.ndb_replication VALUES ('test', 't1', 0, NULL, 'NDB$MAX(mycol)');Inserting a 0 into the
server_idindicates that all SQL nodes accessing this table should use conflict resolution. If you want to use conflict resolution on a specific mysqld only, use the actual server ID.Inserting
NULLinto thebinlog_typecolumn has the same effect as inserting 0 (NBT_DEFAULT); the server default is used.Create the
test.t1table:CREATE TABLE test.t1 (columnsmycol INT UNSIGNED,columns) ENGINE=NDB;Now, when updates are done on this table, conflict resolution will be applied, and the version of the row having the greatest value for
mycolwill be written to the slave.
Note
Other
binlog_typeoptions — such asNBT_UPDATED_ONLY_USE_UPDATEshould be used in order to control logging on the master via thendb_replicationtable rather than by using command-line options.NDB$OLD()example. Suppose anNDBtable such as the one defined here is being replicated, and you wish to enable “same timestamp wins” conflict resolution for updates to this table:CREATE TABLE test.t2 ( a INT UNSIGNED NOT NULL, b CHAR(25) NOT NULL,columns, mycol INT UNSIGNED NOT NULL,columns, PRIMARY KEY pk (a, b) ) ENGINE=NDB;The following steps are required, in the order shown:
First — and prior to creating
test.t2— you must insert a row into themysql.ndb_replicationtable, as shown here:INSERT INTO mysql.ndb_replication VALUES ('test', 't2', 0, NULL, 'NDB$OLD(mycol)');Possible values for the
binlog_typecolumn are shown earlier in this section. The value'NDB$OLD(mycol)'should be inserted into theconflict_fncolumn.Create an appropriate exceptions table for
test.t2. The table creation statement shown here includes all required columns; any additional columns must be declared following these columns, and before the definition of the table's primary key.CREATE TABLE test.t2$EX ( server_id SMALLINT UNSIGNED, master_server_id INT UNSIGNED, master_epoch BIGINT UNSIGNED, count BIGINT UNSIGNED, a INT UNSIGNED NOT NULL, b CHAR(25) NOT NULL, [additional_columns,] PRIMARY KEY(server_id, master_server_id, master_epoch, count) ) ENGINE=NDB;Create the table
test.t2as shown previously.
These steps must be followed for every table for which you wish to perform conflict resolution using
NDB$OLD(). For each such table, there must be a corresponding row inmysql.ndb_replication, and there must be an exceptions table in the same database as the table being replicated.
