This section briefly describes how to set up complete replication of a MySQL server. It assumes that you want to replicate all databases on the master and have not previously configured replication. You must shut down your master server briefly to complete the steps outlined here.
This procedure is written in terms of setting up a single slave, but you can repeat it to set up multiple slaves.
Although this method is the most straightforward way to set up a slave, it is not the only one. For example, if you have a snapshot of the master's data, and the master already has its server ID set and binary logging enabled, you can set up a slave without shutting down the master or even blocking updates to it. For more details, please see Section 6.10, “Replication FAQ”.
If you want to administer a MySQL replication setup, we suggest that you read this entire chapter through and try all statements mentioned in Section 13.6.1, “SQL Statements for Controlling Master Servers”, and Section 13.6.2, “SQL Statements for Controlling Slave Servers”. You should also familiarize yourself with the replication startup options described in Section 6.8, “Replication Startup Options”.
Note: This procedure and some of
the replication SQL statements shown in later sections refer to
the SUPER privilege. Prior to MySQL 4.0.2, use
the PROCESS privilege instead.
Make sure that you have a recent version of MySQL installed on the master and slaves, and that these versions are compatible according to the table shown in Section 6.5, “Replication Compatibility Between MySQL Versions”.
If you encounter a problem, please do not report it as a bug until you have verified that the problem is present in the latest MySQL release.
Set up an account on the master server that the slave server
can use to connect. This account must be given the
REPLICATION SLAVE privilege. If the account
is used only for replication (which is recommended), you don't
need to grant any additional privileges.
MySQL Enterprise.
Subscribers to the MySQL Network Monitoring and Advisory
Service are quickly notified if there is a replication
master and no account with the REPLICATION
SLAVE privilege. For more information see,
http://www.mysql.com/products/enterprise/advisors.html.
Suppose that your domain is mydomain.com
and that you want to create an account with a username of
repl such that slave servers can use the
account to access the master server from any host in your
domain using a password of slavepass. To
create the account, use this GRANT
statement:
mysql>GRANT REPLICATION SLAVE ON *.*->TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
For MySQL versions older than 4.0.2, the REPLICATION
SLAVE privilege does not exist. Grant the
FILE privilege instead:
mysql>GRANT FILE ON *.*->TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
For additional information about setting up user accounts and privileges, see Section 5.8, “MySQL User Account Management”.
Flush all the tables and block write statements by executing a
FLUSH TABLES WITH READ LOCK statement:
mysql> FLUSH TABLES WITH READ LOCK;
For InnoDB tables, note that FLUSH
TABLES WITH READ LOCK blocks
COMMIT operations, too. (This is true as of
MySQL version 4.0.20.) When you have acquired your global read
lock, you can start a filesystem snapshot of your
InnoDB tables. Internally (inside the
InnoDB storage engine) the snapshot won't
be consistent (because the InnoDB caches
are not flushed), but there's no need to worry at all, because
InnoDB will resolve this at startup, and
consequently deliver a consistent result. This means that
InnoDB will perform a crash recovery when
started on this snapshot, but it will not be corrupted. If you
want to have a consistent snapshot of your
InnoDB tables, there's no way around taking
down the MySQL server, though.
Leave running the client from which you issue the
FLUSH TABLES statement so that the read
lock remains in effect. (If you exit the client, the lock is
released.) Then take a snapshot of the data on your master
server.
The easiest way to create a snapshot is to use an archiving program to make a binary backup of the databases in your master's data directory. For example, use tar on Unix, or PowerArchiver, WinRAR, WinZip, or any similar software on Windows. To use tar to create an archive that includes all databases, change location into the master server's data directory, then execute this command:
shell> tar -cvf /tmp/mysql-snapshot.tar .
If you want the archive to include only a database called
this_db, use this command instead:
shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db
Then copy the archive file to the /tmp
directory on the slave server host. On that machine, change
location into the slave's data directory, and unpack the
archive file using this command:
shell> tar -xvf /tmp/mysql-snapshot.tar
You may not want to replicate the mysql
database if the slave server has a different set of user
accounts from those that exist on the master. In this case,
you should exclude it from the archive. You also need not
include any log files in the archive, or the
master.info or
relay-log.info files.
While the read lock placed by FLUSH TABLES WITH READ
LOCK is in effect, read the value of the current
binary log name and offset on the master:
mysql > SHOW MASTER STATUS;
+---------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| mysql-bin.003 | 73 | test | manual,mysql |
+---------------+----------+--------------+------------------+
The File column shows the name of the log
and Position shows the offset within the
file. In this example, the binary log file is
mysql-bin.003 and the offset is 73. Record
these values. You need them later when you are setting up the
slave. They represent the replication coordinates at which the
slave should begin processing new updates from the master.
If the master has been running previously without binary
logging enabled, the log name and position values displayed by
SHOW MASTER STATUS or mysqldump
--master-data will be empty. In that case, the
values that you need to use later when specifying the slave's
log file and position are the empty string
('') and 4.
After you have taken the snapshot and recorded the log name and offset, you can re-enable write activity on the master:
mysql> UNLOCK TABLES;
If you are using InnoDB tables, ideally you
should use the InnoDB Hot
Backup tool, which takes a consistent snapshot
without acquiring any locks on the master server, and records
the log name and offset corresponding to the snapshot to be
later used on the slave. Hot Backup is an
additional non-free (commercial) tool that is not included in
the standard MySQL distribution. See the
InnoDB Hot Backup home
page at http://www.innodb.com/manual.php for
detailed information.
Without the Hot Backup tool, the quickest
way to take a binary snapshot of InnoDB
tables is to shut down the master server and copy the
InnoDB data files, log files, and table
format files (.frm files). To record the
current log file name and offset, you should issue the
following statements before you shut down the server:
mysql>FLUSH TABLES WITH READ LOCK;mysql>SHOW MASTER STATUS;
Then record the log name and the offset from the output of
SHOW MASTER STATUS as was shown earlier.
After recording the log name and the offset, shut down the
server without unlocking the tables to
make sure that the server goes down with the snapshot
corresponding to the current log file and offset:
shell> mysqladmin -u root shutdown
An alternative that works for both MyISAM
and InnoDB tables is to take an SQL dump of
the master instead of a binary copy as described in the
preceding discussion. For this, you can use mysqldump
--master-data on your master and later load the SQL
dump file into your slave. However, this is slower than doing
a binary copy.
Make sure that the [mysqld] section of the
my.cnf file on the master host includes a
log-bin option. The section should also
have a
server-id=
option, where master_idmaster_id must be a
positive integer value from 1 to
232 – 1. For example:
[mysqld] log-bin=mysql-bin server-id=1
If those options are not present, add them and restart the server. The server cannot act as a replication master unless binary logging is enabled.
For the greatest possible durability and consistency in a
replication setup using InnoDB with
transactions, you should use
innodb_flush_log_at_trx_commit=1,
sync_binlog=1, and
innodb_safe_binlog in your master
my.cnf file.
Stop the server that is to be used as a slave and add the
following lines to its my.cnf file:
[mysqld]
server-id=slave_id
The slave_id value, like the
master_id value, must be a positive
integer value from 1 to 232 –
1. In addition, it is necessary that the ID of the slave be
different from the ID of the master. For example:
[mysqld] server-id=2
If you are setting up multiple slaves, each one must have a
unique server-id value that differs from
that of the master and from each of the other slaves. Think of
server-id values as something similar to IP
addresses: These IDs uniquely identify each server instance in
the community of replication partners.
If you do not specify a server-id value, it
is set to 1 if you have not defined
master-host; otherwise it is set to 2. Note
that in the case of server-id omission, a
master refuses connections from all slaves, and a slave
refuses to connect to a master. Thus, omitting
server-id is good only for backup with a
binary log.
If you made a binary backup of the master server's data, copy it to the slave server's data directory before starting the slave. Make sure that the privileges on the files and directories are correct. The system account that you use to run the slave server must be able to read and write the files, just as on the master.
If you made a backup using mysqldump, start the slave first. The dump file is loaded in a later step.
Start the slave server. If it has been replicating previously,
start the slave server with the
--skip-slave-start option so that it doesn't
immediately try to connect to its master. You also may want to
start the slave server with the
--log-warnings option to get more messages in
the error log about problems (for example, network or
connection problems). The option is enabled by default as of
MySQL 4.0.19 and 4.1.2, but as of MySQL 4.0.21 and 4.1.3,
aborted connections are not logged to the error log unless the
value is greater than 1.
If you made a backup of the master server's data using mysqldump, load the dump file into the slave server:
shell> mysql -u root -p < dump_file.sql
Execute the following statement on the slave, replacing the option values with the actual values relevant to your system:
mysql>CHANGE MASTER TO->MASTER_HOST='->master_host_name',MASTER_USER='->replication_user_name',MASTER_PASSWORD='->replication_password',MASTER_LOG_FILE='->recorded_log_file_name',MASTER_LOG_POS=recorded_log_position;
The following table shows the maximum allowable length for the string-valued options:
MASTER_HOST |
60 |
MASTER_USER |
16 |
MASTER_PASSWORD |
32 |
MASTER_LOG_FILE |
255 |
Start the slave threads:
mysql> START SLAVE;
After you have performed this procedure, the slave should connect to the master and catch up on any updates that have occurred since the snapshot was taken.
If you have forgotten to set the server-id
option for the master, slaves cannot connect to it.
If you have forgotten to set the server-id
option for the slave, you get the following error in the slave's
error log:
Warning: You should set server-id to a non-0 value if master_host is set; we will force server id to 2, but this MySQL server will not act as a slave.
You also find error messages in the slave's error log if it is not able to replicate for any other reason.
Once a slave is replicating, you can find in its data directory
one file named master.info and another named
relay-log.info. The slave uses these two
files to keep track of how much of the master's binary log it has
processed. Do not remove or edit these files
unless you know exactly what you are doing and fully understand
the implications. Even in that case, it is preferred that you use
the CHANGE MASTER TO statement to change
replication parameters. The slave will use the values specified in
the statement to update the status files automatically.
Note: The content of
master.info overrides some of the server
options specified on the command line or in
my.cnf. See
Section 6.8, “Replication Startup Options”, for more details.
Once you have a snapshot of the master, you can use it to set up other slaves by following the slave portion of the procedure just described. You do not need to take another snapshot of the master; you can use the same one for each slave.

User Comments
For those who want their server to be both master
and slave at the same time, please note that you
should have only one 'server-id' in your my.cnf file; if
you copy the two sections of statements (Paras. 5
and 7) above into
your my.cnf , you will end up having a connection
problem like:
020821 17:34:47 Slave: connected to
master 'repl@192.168.60.1:3306', replication
started in log 'FIRST' at position 32
020821 17:34:47 Slave: received 0 length
packet from server, apparent master
shutdown:
020821 17:34:47 Slave: Failed reading log
event, reconnecting to retry, log 'FIRST' position
32
020821 17:34:47 Slave: reconnected to
master 'repl@192.168.60.1:3306',replication
resumed in log 'FIRST' at position 32
020821 17:34:47 Slave: received 0 length
packet from server, apparent master
shutdown:
You do not need the line
master-port=<TCP/IP port for master>
of the slave, if you not changed the port. Normal :
3306
To add a user for the master server you need this
line
mysql> GRANT FILE ON *.* TO repl@"%"
IDENTIFIED BY '<password>';
You have to change "%" to the IP Adress from the
SLAVE.
Example: mysql> GRANT FILE ON *.* TO
repl@192.168.0.2 IDENTIFIED BY 'yourpass';
A few things I came across while setting up
replication:
- Passwords can only be 16 characters long. This will
cause 'Access Denied' errors while trying to connect
to the master if set too long.
- When running replication numerous files are
created that can cause problems getting back on
track if something goes wrong. If there are
problems after you edit your my.cnf and restart
mysqld here's some cleaning up that needs to be
done while the server is shutdown (your file names
might differ):
1) On the slave (in the mysql data dir): remove
master.info file, remove all binary files created and
their indexes, remove the .err and .pid files, remove
the log.info file.
2) On the master (in the mysql data dir): remove all
binary files created and their indexes, remove
the .err and .pid files.
3) If for some reason you need to redo replication I
have found it is best to tar up the mnaster and put a
fresh copy of the database on the slave and start
again rather than trying to resolve every issue the
slave spits out. Although, it should be noted that this
is not always possible - it's a judgement call.
I beat my head against the wall trying to figure
this one out:
These instructions assume that you do not
previously have binary loggin on the master
server. If you do have binary logging on (which
you should have if you follow the install
instructions), and you follow these instructions,
you will have problems.
For instance, if logging is on the master and you
create a database and then follow the replication
instructions, replication will not work. This is
because the replication process will try to
replicate the create database command on the slave
and fail because the database is already exists
(because you brought it over with the tar file
from the master).
To work around this you can either drop the
database on the slave or do a 'reset master;' on
the master (this will delete inactive binary logs
on the master so be careful).
Its worth mentionning that if your server-id
values are too large, the communication dies every
time it starts and you'll have to change the IDs,
then reset things to get started again.
Our Main mysql server (3.23.54) has many,many databases. Curently I run a replication setup for redundency purpose, and it's working well.
I want to setup a server with only one of the db's replicated. I can't grant a user file priv only one one db. Is there a way to setup so that the salve won't be able to read all of the dbs' ?
When setting up mysql replication, you may find it necessary to test your username and password settings; in my scenario, I do replication through an SSH tunnel to our live server. If you're doing this, there're a couple of things to note:
1. the GRANT FILE command should be set so that the replication user is allowed access from the server
2. when testing the username/password using the mysql login prompt, this will fail if you've followed the instructions above AND have specified a database to connect to. If you leave the dB name out, the login will work.
Items 3 and 4 seem to be reversed, or at least part of 4 has to be done before you can accomplish all of #3 on a system with no previous replication set up. Specifically "show master status" won't show anything until you update the my.cnf as directed in step #4.
Also surprised the replication FAQ and here do not have anything about: "Error updating slave list: query error" in the error log. I am running 4.0.7-gamma and I had to still "grant file" before this error would go away (from step #2). Found at least a direction to go in from this site:
http://www.faqts.com/knowledge_base/index.phtml/fid/398
There they have a question: "What does the Error updating slave list: query error mean ?" ...
Also step 8 should probably mention something about master_port for people like me that have changed the Port number MySQL daemon is running on. Thanks to the earlier note on that...
Also in step #4 you might want to add a line for binlog-ignore-db=< > or at least mention it...
Executing a FLUSH TABLES WITH READ LOCK doesn't block write queries globally across all of your databases. You have to connect to each database individually and execute the command for it to be effective. (at least on 3.23.56)
The syntax for starting a slave thread is backwards in the documentation. It's "SLAVE START" not "START SLAVE" (again at least under 3.23.56)
Tips for minimizing downtime on Hot MySQL Database servers :
- Start with increasing max_connections value in MySQL before restarting server for binary logging. This is necessary since when you lock tables all new connections will be in que for processing.
- Always copy update log to a safe place too. If you forget getting position of update log for some reason, you can always use mysqlbinlog utility to find out position on binary log.
- While getting copies of database files from MySQL
use unix 'cp' instead of tar. If possible try to use different destination hard drive instead of copying into same hard drive (eg don't copy database files on hda1 to hda1 try to copy hdb1)
Here goes a tip that could saved me a LOT of problems if was here instead of in the CHANGE MASTER command page (where wasn't exactaly what I'm posting here besides):
to make a computer stoping to sync from another computer run STOP SLAVE, shutdown the server, delete `master.info'.
I had aproblem when the master previously was a slave, then when I set up the replication both where replicating from the other... just destroyied a database... :(
Here is what I had to do to set up replication with LOAD DATA FROM MASTER:
1. Edit the my.cnf file on the slave and on the master server:
master my.cnf:
[mysqld]
server-id = 1
log-bin
slave my.cnf:
[mysqld]
server-id = 2
master-host = master-host.net
master-user = repl
master-password = repl_pass
replicate-do-db = database1
replicate-do-db = database2
log-warnings
2. Restart both the slave and the master.
3. On the master do:
GRANT SUPER,REPLICATION CLIENT,REPLICATION SLAVE,RELOAD ON *.* TO repl@"%" IDENTIFIED BY 'repl_pass';
4. On the slave do:
LOAD DATA FROM MASTER;
The slave should now download the databases specified with replicate-do-db in the slaves my.cnf, and be replicating new data.
I couldn't get the replication working on Solaris (SunOS 5.8) with MySQL MAX 4.0.15 precompiled binary with IP addresses. When I tried to start the replication it was always complaining about not being able to login as repl@localhost. Everything started working after I put the IP address to /etc/hosts and put the name of the machine instead of IP address to /etc/my.cnf.
There is a limitation on the length of password stored in master.info file. The password can not be longer than 16 characters, otherwise it will be truncated by MySQL (possibly causing "Access Denied" error messages when slave connects to master).
Im not sure but about this,someone correct me if im wrong:
If you have Master database on different platform than the slaves (For example, Sun/ Intel) you should not copy the binary format databases from master straight to the slaves as there might be endian problems. You should use use mysqldump instead to do the copy from slave to master.
Here's how to replicate via LOAD DATA FROM MASTER; with InnoDB tables: (this is problematic for "hot" databases)
On master:
Export any databases with InnoDB tables via mysqldump. Keep the export on the master server.
Drop all of the above tables.
Prepare the master for replication as described above (lock tables, check log status, unlock tables).
On slave:
Prepare slave for replication (CHANGE MASTER...)
LOAD DATA FROM MASTER;
(If you get ERROR 1189: Net error reading from master that may mean that you have InnoDB tables left on the master - if so go back to master, export and drop those databases (or at least the tables). I've also seen this error when the file system on the slave is full)
If that goes well, START SLAVE;
Back to master:
Now import the databases with InnoDB changes. The databases will propogate to the slave server, InnoDB and all :-)
[An alternate plan, I suppose, would be to simply export ALL tables on master, set up replication, and re-import all tables - messy but it seems to support more things that way]
This is a correction to snix's comments:
On the master do:
GRANT SELECT, PROCESS, FILE, SUPER, REPLICATION CLIENT, REPLICATION SLAVE, RELOAD ON *.* TO repl@'%' IDENTIFIED BY 'repl_pass';
On the slave do:
LOAD DATA FROM MASTER;
tar -cvf does not realy work, since it does not copy empty files. therefore on linux i used zip instead of tar
I am using MySQL 4.0.18 and kept getting an exception in the logs saying the user did not have REPLICATION_SLAVE permission even after I submitted the GRANT REPLICATION_SLAVE command.
Then i realised there was no RELICATION_SLAVE field in the user table. I had to run the mysql_fix_privilege_tables.sql script to upgrade the privilage tables like this
SOURCE C:\mysql\scripts\mysql_fix_privilege_tables.sql
then it worked fine.
If you are trying to replicate just one database, the replication won't work unless you add:
replicate-do-db=[name of database to replicate]
to the my.cnf file of the slave database (under [mysqld]).
ex:
replicate-do-db=backup2
I did a replication using the mysqldump procedure.
The directions state to use the information from the Show Master Status command. However when I used the POS number from the command the slave sql process would fail with a 'duplicates' warning.
I opened the dump file and looked at the very bottom. I used the POS number listed in the dump file and that worked.
My first experiences with using mysqldump to prepare a slave for replication didn't work out so well, but since I've moved to 4.1 I've had great success with importing from a dump of the master. This also gets around the need to run all the migration scripts when using the tarball method to go from an older master to a newer client.
Don't forget to lock tables before taking your dump (hehe), then get the master status before you unlock.
If you're running low on space where you can't have two copies of your data on the same system, then you can use rsync to create a copy of your data. I setup an rsync server on the master and then synced up the slave while it was still running. Obviously this isn't a clean snapshot, so when I performed the "READ LOCK", I did another sync and it went very quick so the master was only locked for a few minutes. Then I setup the slave like the instructions say and now I have a working slave setup with very minimal downtime for the master.
--Ajay
Be sure both master and slave have the same collation_server variable value.
If you see that your slave is stuck in "Registering slave on master" phase (with SHOW SLAVE STATUS command) after SLAVE START check that your slave's configuration includes report-host option. This applies at least to MySQL 4.1
Tested on MySQL versions 4.0.20
1. Edit the my.cnf file on the slave and on the master server:
-master my.cnf:
[mysqld]
server-id = 1
log-bin
-slave my.cnf:
[mysqld]
server-id = 2
#replicate-do-db = database1 # for Replicating specific databases
2. Restart both the slave and the master.
3. SQL SYNTAX:
--On the master do
mysql> GRANT SUPER,REPLICATION CLIENT,REPLICATION SLAVE,RELOAD ON *.* TO repl@"slave.host" IDENTIFIED BY 'password';
--On the SLAVE do
mysql> CHANGE MASTER to MASTER_HOST='master.host’,MASTER_PORT=3306,
MASTER_USER='repl',MASTER_PASSWORD='password',MASTER_LOG_FILE='',MASTER_LOG_POS=4;
mysql> STOP SLAVE; #--If already started
mysql> START SLAVE;
4. On the slave do:
mysql> LOAD DATA FROM MASTER;
The slave should now download the databases specified with replicate-do-db in the slaves my.cnf, and be replicating new data.
NOTE: Please sure that the MASTER_USER had required privilege .
One idea I've not tested when setting up a new slave (when you already have at least one slave) is:
- Stop the existing slave (slave a)
- Copy the /var/lib/mysql data from slave a to the new slave (slave b)
- Query slave a for its replication log position
- Start slave a again
- Start slave b from the given replication log position
This method had the advantage that you don't have to put any write locks in place on the master.
In response to [name withheld] on March 23 2004 2:07am who said:
========================================
tar -cvf does not realy work, since it does not copy empty files. therefore on linux i used zip instead of tar
========================================
This is not correct. tar DOES COPY empty files.
Roumen Semov
If you are setting up replication through an SSH channel, be sure to specify "127.0.0.1" as the address of the database, not "localhost", as MySQL will use "localhost" as a trigger to use a pipe for the connection instead of TCP/IP, and thus will fail.
LOAD DATA FROM MASTER is deprecated.
See:
http://dev.mysql.com/doc/refman/5.0/en/load-data-from-master.html
For Debian users : after copying all mysql data files from master to slave you can get the following error message :
---
/usr/bin/mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'debian-sys-maint'@'localhost' (using password: YES)'
---
* Which means that Mysql password for user 'debian-sys-maint' isn't the same as in file /etc/mysql/debian.cnf.
* Because this password is randomly generated, they are different for each installation, and we have to 'synchronize' this password between debian.cnf file and Mysql privileges.
1 - On the master, get a copy of the password string in /etc/mysql/debian.cnf
2 - On the slave, stop the Mysql server, edit /etc/mysql/debian.cnf and replace the password by the one of the master. Start the slave server.
If you want to change it
1 - Launch a Mysql client and select 'mysql' database
2 - run this : UPDATE `user` SET `Password` = password('[password]') where user='debian-sys-maint'
(the password seems to be encrypted but is not)
3 - stop the Mysql server (you get an error for 'debian-sys-maint')
4 - change and put same [password] in /etc/mysql/debian.cnf file
For people getting:
"ERROR 1218 (08S01): Error connecting to master: Lost connection to MySQL server during query"
Make sure that ,on you're master replication server, you change the following line in your my.cnf:
bind-address 127.0.0.1
to
#bind-address 127.0.0.1
Or change the address to your FQDN or ip-addres
Add your own comment.