{"id":262,"date":"2009-08-20T09:23:38","date_gmt":"2009-08-20T14:23:38","guid":{"rendered":"http:\/\/www.1oc.com\/blog\/?p=262"},"modified":"2009-08-20T09:23:38","modified_gmt":"2009-08-20T14:23:38","slug":"how-to-set-up-database-replication-in-mysql","status":"publish","type":"post","link":"http:\/\/blog.1oc.com\/?p=262","title":{"rendered":"How To Set Up Database Replication In MySQL"},"content":{"rendered":"<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">This tutorial describes how to set up database replication in MySQL. MySQL replication allows you to have an exact copy of a database from a master server on another server (slave), and all updates to the database on the master server are immediately replicated to the database on the slave server so that both databases are in sync. This is not a backup policy because an accidentally issued DELETE command will also be carried out on the slave; but replication can help protect against hardware failures though.<\/span><\/p>\n<div><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif;\"><span><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">In this tutorial I will show how to replicate the database\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span> from the master with the IP address\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>192.168.0.100<\/em><\/span> to a slave. Both systems (master and slave) are running\u00a0<strong>Debian Sarge<\/strong>; however, the configuration should apply to almost all distributions with little or no modification.<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Both systems have MySQL installed, and the database\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span> with tables and data is already existing on the master, but not on the slave.<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">I want to say first that this is not the only way of setting up such a system. There are many ways of achieving this goal but this is the way I take. I do not issue any guarantee that this will work for you!<\/span><\/p>\n<h4><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: small;\">1 Configure The Master<\/span><\/h4>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">First we have to edit\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>\/etc\/mysql\/my.cnf<\/em><\/span>. We have to enable networking for MySQL, and MySQL should listen on all IP addresses, therefore we comment out these lines (if existant):<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\"> <\/span><\/p>\n<pre>#skip-networking\n#bind-address            = 127.0.0.1<\/pre>\n<p>Furthermore we have to tell MySQL for which database it should write logs (these logs are used by the slave to see what has changed on the master), which log file it should use, and we have to specify that this MySQL server is the master. We want to replicate the database\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>, so we put the following lines into\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>\/etc\/mysql\/my.cnf<\/em><\/span>:<\/p>\n<pre>log-bin = \/var\/log\/mysql\/mysql-bin.log\nbinlog-do-db=exampledb\nserver-id=1<\/pre>\n<p>Then we restart MySQL:<\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">\/etc\/init.d\/mysql restart<\/span><\/em><\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Then we log into the MySQL database as\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>root<\/em><\/span> and create a user with replication privileges:<\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">mysql -u root -p<br \/>\nEnter password:<\/span><\/em><\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Now we are on the MySQL shell.<\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">GRANT REPLICATION SLAVE ON *.* TO &#8216;slave_user&#8217;@&#8217;%&#8217; IDENTIFIED BY &#8216;&lt;some_password&gt;&#8217;; <\/span><\/em><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">(Replace\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>&lt;some_password&gt;<\/em><\/span> with a real password!)<\/span><span style=\"font-size: x-small;\"><em><br \/>\nFLUSH PRIVILEGES;<\/em><\/span><\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Next (still on the MySQL shell) do this:<\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">USE exampledb;<br \/>\nFLUSH TABLES WITH READ LOCK;<br \/>\nSHOW MASTER STATUS;<\/span><\/em><\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">The last command will show something like this:<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\"> <\/span><\/p>\n<pre>+---------------+----------+--------------+------------------+\n| File          | Position | Binlog_do_db | Binlog_ignore_db |\n+---------------+----------+--------------+------------------+\n| mysql-bin.006 | 183      | exampledb    |                  |\n+---------------+----------+--------------+------------------+\n1 row in set (0.00 sec)<\/pre>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Write down this information, we will need it later on the slave!<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Then leave the MySQL shell:<\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\"><em>quit;<\/em><\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\"><em> <\/em><\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\"><em><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">There are two possibilities to get the existing tables and data from\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span> from the master to the slave. The first one is to make a database dump, the second one is to use the<\/span> <span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\"><em>LOAD DATA FROM MASTER;<\/em><\/span> <span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">command on the slave. The latter has the disadvantage the the database on the master will be\u00a0<strong>locked<\/strong> during this operation, so if you have a large database on a high-traffic production system, this is not what you want, and I recommend to follow the first method in this case. However, the latter method is very fast, so I will describe both here.<\/span><\/em><\/span><\/p>\n<p><em><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">If you want to follow the first method, then do this:<\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">mysqldump -u root -p&lt;password&gt; &#8211;opt exampledb &gt; exampledb.sql <\/span><\/em><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">(Replace\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>&lt;password&gt;<\/em><\/span> with the real password for the MySQL user\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>root<\/em><\/span>!\u00a0<strong>Important:<\/strong> There is\u00a0<strong>no<\/strong> space between\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>-p<\/em><\/span> and<span style=\"font-family: 'Courier New', Courier, mono;\"><em>&lt;password&gt;<\/em><\/span>!)<\/span><\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">This will create an SQL dump of\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span> in the file\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb.sql<\/em><\/span>. Transfer this file to your slave server!<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">If you want to go the\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>LOAD DATA FROM MASTER;<\/em><\/span> way then there is nothing you must do right now.<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\"><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Finally we have to unlock the tables in\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>:<\/span><\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">mysql -u root -p<br \/>\nEnter password:<br \/>\nUNLOCK TABLES;<br \/>\nquit;<\/span><\/em><\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Now the configuration on the master is finished. On to the slave&#8230;<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\"><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: small;\"><strong>2 Configure The Slave<\/strong><\/span><\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">On the slave we first have to create the database\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>:<\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">mysql -u root -p<br \/>\nEnter password:<br \/>\nCREATE DATABASE exampledb;<br \/>\nquit;<\/span><\/em><\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono;\"><em> <\/em><\/span><\/p>\n<p><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\"><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">If you have made an SQL dump of\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span> on the master and have transferred it to the slave, then it is time now to import the SQL dump into our newly created\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span> on the slave:<\/span><\/span><\/em><\/span><\/p>\n<p><em><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">mysql -u root -p&lt;password&gt; exampledb &lt; \/path\/to\/exampledb.sql <\/span><\/em><span style=\"font-family: 'Courier New', Courier, mono;\"><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">(Replace\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>&lt;password&gt;<\/em><\/span> with the real password for the MySQL user\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\">root<\/span>!<strong>Important:<\/strong> There is\u00a0<strong>no<\/strong> space between\u00a0<em><span style=\"font-family: 'Courier New', Courier, mono;\">-p<\/span><\/em> and\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>&lt;password&gt;<\/em><\/span>!)<\/span><\/span><\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">If you want to go the\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>LOAD DATA FROM MASTER;<\/em><\/span> way then there is nothing you must do right now.<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Now we have to tell MySQL on the slave that it is the slave, that the master is\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>192.168.0.100<\/em><\/span>, and that the master database to watch is\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>. Therefore we add the following lines to<span style=\"font-family: 'Courier New', Courier, mono;\"><em>\/etc\/mysql\/my.cnf<\/em><\/span>:<\/span><\/p>\n<p><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\"> <\/span><\/p>\n<pre>server-id=2\nmaster-host=192.168.0.100\nmaster-user=slave_user\nmaster-password=secret\nmaster-connect-retry=60\nreplicate-do-db=exampledb<\/pre>\n<pre><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Then we restart MySQL:<\/span>\n\n<span style=\"font-size: x-small;\"><em><span style=\"font-family: 'Courier New', Courier, mono;\">\/etc\/init.d\/mysql restart<\/span><\/em><\/span>\n\n<span style=\"font-family: 'Courier New', Courier, mono;\"><span style=\"font-size: x-small; \"><em>\n<\/em><\/span><\/span>\n\n<span style=\"font-family: 'Courier New', Courier, mono;\"><span style=\"font-size: xx-small; \"><em>\u00a0<\/em><\/span><\/span>\n<span style=\"font-family: 'Courier New', Courier, mono;\"><em>\n<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">If you have not imported the master\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>\u00a0with the help of an SQL dump, but want to go the\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>LOAD DATA FROM MASTER;<\/em><\/span>\u00a0way, then it is time for you now to get the data from the master<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>:<\/span>\n\n<span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">mysql -u root -p\nEnter password:\nLOAD DATA FROM MASTER;\nquit;<\/span><\/em><\/span>\n\n<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">If you have phpMyAdmin\u00a0installed on the slave you can now check if all tables\/data from the master\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>\u00a0is also available on the slave\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>.<\/span>\n\n<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif;\">\u00a0<\/span>\n<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif;\">\n<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Finally, we must do this:<\/span>\n\n<span style=\"font-size: x-small;\"><em><span style=\"font-family: 'Courier New', Courier, mono;\">mysql -u root -p\nEnter password:\nSLAVE STOP;<\/span><\/em><\/span>\n\n<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">In the next command (still on the MySQL shell) you have to replace the values appropriately:<\/span>\n\n<span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">CHANGE MASTER TO MASTER_HOST='192.168.0.100', MASTER_USER='slave_user', MASTER_PASSWORD='<\/span><span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">&lt;some_password&gt;<\/span><\/em><\/span><span style=\"font-size: x-small;\">', MASTER_LOG_FILE='mysql-bin.006', MASTER_LOG_POS=183;<\/span><\/em><\/span>\n\n<span style=\"font-family: 'Courier New', Courier, mono;\"><span style=\"font-size: x-small; \">\n<\/span><\/span>\n\n<span style=\"font-family: 'Courier New', Courier, mono;\">\n<ul>\n\t<li><em><span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\">MASTER_HOST<\/span><\/em>\u00a0<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">is the IP address or hostname of the master (in this example it is<\/span>\u00a0<span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\"><em>192.168.0.100<\/em><\/span><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">).<\/span><\/li>\n\t<li><em><span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\">MASTER_USER<\/span><\/em><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">\u00a0is the user we granted replication privileges on the master.<\/span><\/li>\n\t<li><em><span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\">MASTER_PASSWORD<\/span><\/em>\u00a0<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">is the password of<\/span>\u00a0<span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\"><em>MASTER_USER<\/em><\/span>\u00a0<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">on the master.<\/span><\/li>\n\t<li><em><span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\">MASTER_LOG_FILE<\/span><\/em>\u00a0<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">is the file MySQL gave back when you ran<\/span>\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">SHOW MASTER STATUS;<\/span><\/em><\/span>\u00a0<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">on the master.<\/span><\/li>\n\t<li><em><span style=\"font-family: 'Courier New', Courier, mono; font-size: x-small;\">MASTER_LOG_POS<\/span><\/em>\u00a0<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">is the position MySQL gave back when you ran<\/span>\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">SHOW MASTER STATUS;<\/span><\/em><\/span><span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">\u00a0on the master.<\/span><\/li>\n<\/ul>\n<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">Now all that is left to do is start the slave. Still on the MySQL shell we run<\/span>\n\n<span style=\"font-family: 'Courier New', Courier, mono;\"><em><span style=\"font-size: x-small;\">START SLAVE;\nquit;<\/span><\/em><\/span>\n\n<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif; font-size: x-small;\">That's it! Now whenever\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>\u00a0is updated on the master, all changes will be replicated to\u00a0<span style=\"font-family: 'Courier New', Courier, mono;\"><em>exampledb<\/em><\/span>\u00a0on the slave. Test it!<\/span>\n\n<span style=\"font-family: Verdana, Arial, Helvetica, sans-serif;\"><span style=\"font-size: x-small; \">\n<\/span><\/span>\n<\/span>\n\n<\/span>\n\n<\/em><\/span><\/pre>\n<p><\/em><\/p>\n<p><\/em><\/p>\n<p><\/span><\/span><\/div>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial describes how to set up database replication in MySQL. MySQL replication allows you to have an exact copy of a database from a master server on another server (slave), and all updates to the database on the master &hellip; <a href=\"http:\/\/blog.1oc.com\/?p=262\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,11],"tags":[],"class_list":["post-262","post","type-post","status-publish","format-standard","hentry","category-data-warehouse","category-web-applications"],"_links":{"self":[{"href":"http:\/\/blog.1oc.com\/index.php?rest_route=\/wp\/v2\/posts\/262","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.1oc.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.1oc.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.1oc.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.1oc.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=262"}],"version-history":[{"count":0,"href":"http:\/\/blog.1oc.com\/index.php?rest_route=\/wp\/v2\/posts\/262\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.1oc.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=262"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.1oc.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=262"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.1oc.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=262"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}