<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dan Cryer - Leeds Web Developer &#187; replication</title>
	<atom:link href="http://www.dancryer.com/tag/replication/feed" rel="self" type="application/rss+xml" />
	<link>http://www.dancryer.com</link>
	<description>Dan Cryer - Leeds Web Developer</description>
	<lastBuildDate>Mon, 02 Aug 2010 10:09:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>MySQL Load-Balanced Cluster Guide – Part 3</title>
		<link>http://www.dancryer.com/2010/01/load-balancing-mysql-with-ha-proxy</link>
		<comments>http://www.dancryer.com/2010/01/load-balancing-mysql-with-ha-proxy#comments</comments>
		<pubDate>Thu, 28 Jan 2010 17:14:00 +0000</pubDate>
		<dc:creator>Dan Cryer</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[PHP Conference 2010]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[servers]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.dancryer.com/?p=434</guid>
		<description><![CDATA[This article is the last in my MySQL Load-Balanced Cluster Guide series, following on from my earlier post today on setting up MySQL Monitoring on the cluster nodes, this article is a guide to setting up the load balancer with HAProxy, using the monitoring scripts we&#8217;ve created to check the node status. HAProxy is a [...]]]></description>
			<content:encoded><![CDATA[<p>This article is the last in my MySQL Load-Balanced Cluster Guide series, following on from my earlier post today on <a href="http://www.dancryer.com/2010/01/mysql-monitoring-with-xinetd">setting up MySQL Monitoring on the cluster nodes</a>, this article is a guide to setting up the load balancer with HAProxy, using the monitoring scripts we&#8217;ve created to check the node status.</p>
<p>HAProxy is a well known, powerful load balancer. Best known for use with HTTP servers, but it can work with any kind of TCP traffic, including MySQL. Upcoming versions will support native MySQL monitoring, so we&#8217;ll be able to retire the custom scripts we created in the previous step, when they&#8217;re available in apt-get.</p>
<p><strong>1. Install HAProxy using the following apt-get command: </strong>apt-get install haproxy</p>
<p><strong>2. Delete the file /etc/haproxy/haproxy.cfg and create a new one with the following contents:</strong></p>
<p><code>global<br />
log 127.0.0.1   local0<br />
maxconn 4096<br />
user haproxy<br />
group haproxy<br />
daemon</code></p>
<p><code> </code></p>
<p><code>defaults<br />
log     global<br />
mode    tcp<br />
option  tcplog<br />
option  dontlognull<br />
retries 3<br />
option redispatch<br />
maxconn 2000<br />
contimeout      4000<br />
clitimeout      50000<br />
srvtimeout      30000<br />
stats enable<br />
stats scope	.</code></p>
<p><code>frontend mysql_cluster<br />
bind {load-balancer-ip}:3306<br />
default_backend	mysql_cluster</code></p>
<p><code>backend mysql_cluster<br />
mode tcp<br />
balance roundrobin<br />
stats enable<br />
option tcpka<br />
option httpchk<br />
server {node-name} {ip-address}:3306 weight 1 check port 9200 inter 5s rise 2 fall 2<br />
server {node-name} {ip-address}:3306 weight 1 check port 9200 inter 5s rise 2 fall 2</p>
<p></code></p>
<p><code>listen stats {load-balancer-ip}:80<br />
mode http<br />
option httpclose<br />
balance roundrobin<br />
stats uri     /<br />
stats realm   Haproxy\ Statistics<br />
stats auth    {username}:{password}<br />
</code></p>
<p>Once you&#8217;ve modified this file with settings appropriate to your environment, you&#8217;ll have a ready to go load balancer for MySQL. It&#8217;ll open port 3306 on the load balancer and forward those connections using round-robin load balancing to your two cluster servers. If either server goes down, it&#8217;ll be removed from the pool and no connections will be sent to it until it comes back up.</p>
<p>Additionally, it&#8217;ll create a statistics interface similar to the following, which you can access by going to your load balancing server&#8217;s address in your browser.</p>
<p><a href="http://www.dancryer.com/wp/wp-content/uploads/2010/01/haproxy.png"><img class="aligncenter size-large wp-image-437" title="HA Proxy" src="http://www.dancryer.com/wp/wp-content/uploads/2010/01/haproxy-1024x566.png" alt="HA Proxy Web Interface" width="450" height="248" /></a></p>
<p>Each cluster node should be listed under the first &#8220;mysql_cluster&#8221; section. They should all appear in green, as they should all be live. If a server is down, it&#8217;ll appear red, as explained in the key at the top of the page. From this interface you can also see how long the load balancer has been up, how long each server has been up, how much downtime each have had, as well as the individual number of downtime incidents. As you can see in the image above, our &#8216;cluster-1&#8242; server has had 21 separate downtime incidents, totalling just over 9 minutes of downtime.</p>
<p>So what do you need to change in your haproxy.cfg file? Here&#8217;s a quick rundown:</p>
<ul>
<li>Firstly, you&#8217;ll need to change the line starting &#8216;bind&#8217; to use your load balancer&#8217;s public IP address.</li>
<li>Secondly, make the same change on the line starting &#8216;listen stats&#8217;. You may also choose to put this service on a different port than port 80.</li>
<li>Next, change the {username} and {password} section of the &#8216;stats auth&#8217; line to ones of your choosing. This provides password protection to your web interface.</li>
<li>Finally, for each of your MySQL cluster nodes, you&#8217;ll need an appropriate &#8216;server&#8217; line in the &#8216;mysql_cluster&#8217; backend group. The things you need to change are {node-name}, to the name of the cluster node you defined earlier (e.g. cluster-1, cluster-2) and {ip-address} to the cluster node&#8217;s internal IP address.</li>
</ul>
<p>You may also wish to change the interval at which the load balancer will poll the MySQL servers, by changing &#8216;inter 5&#8242; to a different number. For more information on HAProxy configuration, their detailed &#8211; if a little unfriendly &#8211; documentation is available <a rel="nofollow" href="http://haproxy.1wt.eu/download/1.3/doc/configuration.txt">here</a>.</p>
<p>The final step to get this running, is to restart haproxy: /etc/init.d/haproxy restart - You should now be able to access both your web interface on port 80 and your brand new MySQL cluster on port 3306!</p>
<p>If you&#8217;ve got any questions about these guides or setting up a similar cluster, please leave a comment below and I&#8217;ll do my best to answer it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dancryer.com/2010/01/load-balancing-mysql-with-ha-proxy/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MySQL Load-Balanced Cluster Guide – Part 2</title>
		<link>http://www.dancryer.com/2010/01/mysql-monitoring-with-xinetd</link>
		<comments>http://www.dancryer.com/2010/01/mysql-monitoring-with-xinetd#comments</comments>
		<pubDate>Thu, 28 Jan 2010 16:28:35 +0000</pubDate>
		<dc:creator>Dan Cryer</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[PHP Conference 2010]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[servers]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.dancryer.com/?p=425</guid>
		<description><![CDATA[Following on from yesterday&#8217;s guide to setting up MySQL master-master replication, the first of today&#8217;s guides is how to set up a script to monitor the status of your MySQL cluster nodes, which we&#8217;ll use in the next guide to set up our proxy. On every one of your MySQL cluster nodes, follow the steps [...]]]></description>
			<content:encoded><![CDATA[<p>Following on from yesterday&#8217;s guide to <a href="/2010/01/mysql-circular-replication">setting up MySQL master-master replication</a>, the first of today&#8217;s guides is how to set up a script to monitor the status of your MySQL cluster nodes, which we&#8217;ll use in the next guide to set up our proxy.</p>
<p>On every one of your MySQL cluster nodes, follow the steps below to get it ready for status reporting:</p>
<p><strong>1. Run the following apt-get command: <em>apt-get install xinetd php5-cli php5-mysql</em></strong> &#8211; We need xinetd to host our status server, and php5 for the status checking script.</p>
<p><strong>2. Put the following code into a new file: /etc/xinetd.d/mysqlchk</strong> &#8211; This creates an xinetd &#8220;server&#8221; on port 9200, using the /opt/mysql-status.php file to generate the response. Our proxy will connect to this server to check the status of the node.</p>
<p><code>#<br />
# /etc/xinetd.d/mysqlchk<br />
#<br />
service mysqlchk<br />
{<br />
flags           = REUSE<br />
socket_type     = stream<br />
protocol        = tcp<br />
port            = 9200<br />
wait            = no<br />
user            = mysql<br />
server          = /opt/mysql-status.php<br />
log_on_failure  += USERID<br />
disable         = no<br />
}</code></p>
<p><strong>3. Add the following line at the bottom of /etc/services</strong> &#8211; This registers your newly created xinetd service with the system to allow it to function.<br />
<code>mysqlchk	9200/tcp	# MySQL Monitoring</code></p>
<p><strong>4. Create the PHP file /opt/mysql-status.php with the code below.</strong><br />
This script tries to connect to your MySQL server, and if it succeeds, checks the &#8216;Seconds_Behind_Master&#8217; value of the slave status to make sure it is not too far behind it&#8217;s master. If either of these checks fail, it will return a 503 error to the client, telling it that the server is down.<br />
<code>#!/usr/bin/php<br />
&lt; ?php<br />
/**<br />
*	MySQL Replication Monitor<br />
*/</code></p>
<p><code>// Connection details:<br />
$_host     = 'localhost';<br />
$_username = '{username}';<br />
$_password = '{password}';<br />
$_timeout  = 60; // Number of seconds behind master this node can fall before being marked as "down".</p>
<p>try<br />
{<br />
$pdo = new PDO('mysql:host='.$_host, $_username, $_password);<br />
$pdo-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);</p>
<p>$stmt   = $pdo-&gt;query('SHOW SLAVE STATUS');<br />
$status = $stmt-&gt;fetch(PDO::FETCH_ASSOC);</p>
<p>if($status == false)<br />
{<br />
serverIsDown('Querying slave status failed.');<br />
}</p>
<p>if(intval($status['Seconds_Behind_Master']) &gt; $_timeout)<br />
{<br />
serverIsDown('Slave is behind.');<br />
}<br />
}<br />
catch(Exception $ex)<br />
{<br />
if(!is_null($pdo))<br />
unset($pdo);</p>
<p>serverIsDown('Failed to connect to MySQL.');<br />
}</p>
<p>unset($pdo);</p>
<p>serverIsUp();</p>
<p>function serverIsDown($message)<br />
{<br />
$output = 'Server is currently down. Message:' . $message;<br />
print "HTTP/1.1 503 Service Unavailable\r\n";<br />
print "Date: " . date('r') . "\r\n";<br />
print "Server: MySQL Monitor/1.0\r\n";<br />
print "Connection: close\r\n";<br />
print "Content-Type: text/plain\r\n";<br />
print "Content-Length: " . strlen($output) . "\r\n";<br />
print "\r\n";<br />
print $output;<br />
die;<br />
}</p>
<p></code></p>
<p><code>function serverIsUp()<br />
{<br />
$output = 'Server is up. All is okay.';<br />
print "HTTP/1.1 200 OK\r\n";<br />
print "Date: " . date('r') . "\r\n";<br />
print "Server: MySQL Monitor/1.0\r\n";<br />
print "Connection: close\r\n";<br />
print "Content-Type: text/plain\r\n";<br />
print "Content-Length: " . strlen($output) . "\r\n";<br />
print "\r\n";<br />
print $output;<br />
die;<br />
}</code></p>
<p><strong>5. chown -fv mysql:mysql /opt/mysql-status.php</strong> &#8211; Give ownership of the status checking script to mysql.<br />
<strong>6. chmod -fv +x /opt/mysql-status.php</strong> &#8211; Give execute permissions on the script.<br />
<strong>7. /etc/init.d/xinetd restart</strong> &#8211; Restart xinetd, to make all of the changes we&#8217;ve just made live.</p>
<p>Having completed the steps above, you will now have a script that checks the current status of your MySQL server, responding to connections on port 9200 of your server. In the next article, I&#8217;ll describe how to set up your load balancing server with HAProxy, and utilise the server we&#8217;ve just created to check which nodes are live at any given time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dancryer.com/2010/01/mysql-monitoring-with-xinetd/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MySQL Load-Balanced Cluster Guide &#8211; Part 1</title>
		<link>http://www.dancryer.com/2010/01/mysql-circular-replication</link>
		<comments>http://www.dancryer.com/2010/01/mysql-circular-replication#comments</comments>
		<pubDate>Wed, 27 Jan 2010 17:35:21 +0000</pubDate>
		<dc:creator>Dan Cryer</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[PHP Conference 2010]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[scaling]]></category>
		<category><![CDATA[servers]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.dancryer.com/?p=409</guid>
		<description><![CDATA[I&#8217;m currently working on setting up a load-balanced many-master MySQL cluster at work, without using MySQL Cluster as it&#8217;s incompatible with our needs. Finding good guides on how to do this has proven incredibly difficult, so I thought I would document the process here. This first post is going to cover setting up the servers [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently working on setting up a load-balanced many-master MySQL cluster at work, without using MySQL Cluster as it&#8217;s incompatible with our needs. Finding good guides on how to do this has proven incredibly difficult, so I thought I would document the process here.</p>
<p>This first post is going to cover setting up the servers themselves and configuring MySQL replication.</p>
<p><strong>1. Set up the following three servers:<br />
</strong></p>
<ul>
<li><strong>Cluster Load Balancer</strong> &#8211; One Public IP, One Internal IP &#8211; Ubuntu Jaunty Basic installation</li>
<li><strong>Cluster MySQL 1</strong> &#8211; One Public IP, One Internal IP &#8211; Ubuntu Jaunty Basic + MySQL Server 5.x</li>
<li><strong>Cluster MySQL 2</strong> &#8211; One Public IP, One Internal IP &#8211; Ubuntu Jaunty Basic + MySQL Server 5.x</li>
</ul>
<p>We&#8217;re using <a rel="nofollow" href="http://manage.aff.biz/z/146/CD2815/">VPS.NET</a>. If you&#8217;re going to do the same, use the &#8216;Ubuntu 8.04 LTS 64-bit Basic Installation&#8217; template for the Load Balancer and &#8216;Ubuntu 8.04 x64 MySQL&#8217; for the MySQL nodes. You&#8217;ll then need to do the following to upgrade to Jaunty:</p>
<ul>
<li>Edit the file &#8216;<em>/etc/update-manager/release-upgrades</em>&#8216; and change the line &#8216;<em>Prompt=lts</em>&#8216; to &#8216;<em>Prompt=normal</em>&#8216;.</li>
<li>Run the command &#8216;<em>do-release-upgrade</em>&#8216;. Let it go through the entire process of installing Intrepid, then reboot.</li>
<li>Repeat the step above again to install of Jaunty.</li>
</ul>
<p><strong>2. On the two MySQL servers, edit /etc/mysql/my.cnf and comment out the line &#8216;<em>bind-address 127.0.0.1</em>&#8216; &#8211; the servers need to allow remote TCP/IP connections.<br />
</strong><br />
<strong>3. On each server, add the following to the /etc/mysql/my.cnf file:<br />
</strong><br />
<code>server-id = 1                         # Increment this number by one for each server, so 1 for cluster-1, 2 for cluster-2<br />
auto_increment_increment = 2          # Set to the number of nodes you have (or are likely to have)<br />
auto_increment_offset = 1             # Set to the same as the server-id<br />
replicate-same-server-id = 0          # To ensure the slave thread doesn't try to write updates that this node has produced.<br />
log-bin                               # Turn on binary logging (neccessary for replication)<br />
log-slave-updates                     # Neccessary for chain or circular replication<br />
relay-log                             # As above<br />
relay-log-index                       # As above</code></p>
<p><strong>Note:</strong> On our servers, we&#8217;ve used an <em>auto_increment_increment </em>of 4, to allow us to add two more nodes to our cluster at a later date, without hitting auto-increment problems.</p>
<p><strong>4. Restart MySQL on both servers.<br />
</strong><br />
<strong>5. On Cluster 1, log into the MySQL Console and run the following queries:<br />
</strong><br />
<code>STOP SLAVE;<br />
CHANGE master TO master_host="cluster-2.yourdomain.com", master_user="{username}", master_password="{password}", master_log_file="mysqld-bin.000001", master_log_pos=98;<br />
START SLAVE;</code></p>
<p><strong>Note:</strong> To verify the master_log_pos value, execute the query: &#8220;SHOW MASTER STATUS;&#8221; and check the Position column. Also, you may wish to use your internal IP addresses for the master_host option.</p>
<p><strong>6. On Cluster 2, log into the MySQL Console and run the following queries:<br />
</strong><br />
<code>STOP SLAVE;<br />
CHANGE master TO master_host="cluster-1.yourdomain.com", master_user="{username}", master_password="{password}", master_log_file="mysqld-bin.000001", master_log_pos=98;<br />
START SLAVE;</code></p>
<p><strong>Note:</strong> If on either server you get an error message at this point, verify that:</p>
<ul>
<li>a) the master_log_file name in the query above matches the ones your servers are generating</li>
<li>b) your username and password for the other server are correct</li>
<li>c) that your servers can communicate with each other using the host names you specified.</li>
<li>Additionally, you may wish to remove AppArmor, as that can interfere with MySQL replication and cause all kinds of miscellaneous problems. To do so, run &#8216;<em>apt-get remove apparmor</em>&#8216; followed by &#8216;<em>apt-get purge apparmor</em>&#8216;.</li>
</ul>
<p>You should now have master to master replication set up and running across your two MySQL servers. To test, create a database on cluster-1, then create a table within that database and insert some data into it. Next, log on to cluster-2 and you should be able to see that newly created table, complete with data.</p>
<p>If you want to ensure that it works both ways, insert some data on cluster-2 and you should see it on cluster-1. You will also want to test that your auto-increment settings are working correctly.</p>
<p>If you&#8217;ve got any questions about this article, or have any problems setting up the replication, please leave a comment below and I&#8217;ll do my best to help. The next article in this guide will cover setting up a proxy on the load balancer and hopefully, implementing failover.</p>
<ul>
<li>Next Step: <a href="http://www.dancryer.com/2010/01/mysql-monitoring-with-xinetd">Setting up MySQL Monitoring on the cluster nodes</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.dancryer.com/2010/01/mysql-circular-replication/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Used the &#8220;Spider Storage Engine&#8221; for MySQL?</title>
		<link>http://www.dancryer.com/2009/11/mysql-spider-storage-engine</link>
		<comments>http://www.dancryer.com/2009/11/mysql-spider-storage-engine#comments</comments>
		<pubDate>Thu, 26 Nov 2009 12:01:31 +0000</pubDate>
		<dc:creator>Dan Cryer</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[spider]]></category>
		<category><![CDATA[storage engine]]></category>

		<guid isPermaLink="false">http://www.dancryer.com/?p=289</guid>
		<description><![CDATA[We&#8217;re doing some research into how to scale our MySQL database from the current Master and Two Slaves set up, to a scalable cluster, ideally without going down the master to master replication route MySQL offer. In doing so, Wade stumbled across the &#8220;Spider&#8221; storage engine, but information seems sorely lacking and the home page [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-292" style="margin-left: 15px; margin-bottom: 15px; border: 1px solid #ccc; background: transparent;" title="Spider for MySQL" src="http://www.dancryer.com/wp/wp-content/uploads/2009/11/spider-logo.jpg" alt="Spider for MySQL" width="130" height="117" />We&#8217;re doing some research into how to scale our MySQL database from the current Master and Two Slaves set up, to a scalable cluster, ideally without going down the master to master replication route MySQL offer. In doing so, Wade stumbled across the <a rel="nofollow" href="http://spiderformysql.com/">&#8220;Spider&#8221; storage engine</a>, but information seems sorely lacking and the home page does very little to help.</p>
<p>From what we&#8217;ve read so far, the Spider Storage Engine is a drop-in replacement for InnoDB. The engine transparently handles both sharding of storage and distributed query processing across a pool of MySQL nodes. Upon creation, you define the column it should look at, and then the range to distribute to each server, and everything else is handled for you. It also appears to be Drizzle compatible. However, apart from that, we know very little else.</p>
<p>I&#8217;m hoping that someone reading this will have used Spider in the past and be able to give their opinions. If you have used it, please drop a comment below with your experiences. We want to know about both positives and negatives, any benchmarks, any glaring pitfalls. We&#8217;ll likely post about our experiences if we end up testing it, but until then, whatever knowledge people have would be very much appreciated.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dancryer.com/2009/11/mysql-spider-storage-engine/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL Replication Issues</title>
		<link>http://www.dancryer.com/2009/09/mysql-replication-issues</link>
		<comments>http://www.dancryer.com/2009/09/mysql-replication-issues#comments</comments>
		<pubDate>Mon, 14 Sep 2009 19:46:04 +0000</pubDate>
		<dc:creator>Dan Cryer</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[PHP Conference 2010]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[scaling]]></category>

		<guid isPermaLink="false">http://www.dancryer.com/?p=139</guid>
		<description><![CDATA[In our ongoing, joyous adventures with scaling MySQL, we hit another stumbling block this morning. We arrived to find out that one of our two MySQL slaves had stopped replicating at 6AM on Saturday morning. This meant that our reporting systems were all running on two day old data, even though we&#8217;d been diligently collecting [...]]]></description>
			<content:encoded><![CDATA[<div>In our ongoing, joyous adventures with scaling MySQL, we hit another stumbling block this morning. We arrived to find out that one of our two MySQL slaves had stopped replicating at 6AM on Saturday morning. This meant that our reporting systems were all running on two day old data, even though we&#8217;d been diligently collecting and storing data all weekend.</div>
<div>Our setup is reasonably standard:</div>
<ul>
<li>One master &#8211; All writes go to this server.</li>
<li>Two slaves:
<ul>
<li>Slave One runs in our office, is a somewhat less powerful machine than the master, but usually keeps up. This slave&#8217;s job is to do a daily backup, as such, it can be up to six hours behind, as the backup takes that long.</li>
<li>Slave Two runs in the same rack as the master at our data centre, this box is of equal spec to the master and is usually 0-2 seconds behind. This slave&#8217;s job is to serve our reporting systems.</li>
</ul>
</li>
<li>Row-based replication.</li>
</ul>
<p>When we arrived, we were hit with Slave Two throwing errors such as: &#8220;Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event&#8217;s master log&#8221;. Slave One was, and has remained, fine. Remo, Ben, and I spent quite some time Googling for a solution, but that turned up absolutely nothing. There were a few suggestions, such as setting &#8220;slave_exec_mode&#8221; to &#8220;IDEMPOTENT&#8221;. This is merely silent error suppression for such errors, and seems to be suggested for environments using master to master replication and/or cluster-based replication.  We were very uncomfortable with using this, as it meant that our slaves could slowly slip completely out of sync on all tables, and we&#8217;d never know about it.</p>
<p>Luckily for us, the affected table is one that we never need to read from on the slaves. It&#8217;s a queue table, which we update on the master, and then need to immediately read those rows from, so we do that on the master too. Our solution became clear later in the afternoon. As MySQL allows you to use different storage engines on your slaves to the master, we went the dirty route. The queue tables on the slaves are now powered by the <a rel="nofollow" href="http://dev.mysql.com/doc/refman/5.1/en/blackhole-storage-engine.html">BlackHole storage engine</a>.</p>
<p>Getting the slave back up and running was a whole task in itself, however, as thousands upon thousands of queries had failed in the time this problem had been occuring. The commonly accepted solution is to do the following:</p>
<blockquote><p>STOP SLAVE;</p>
<p>SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;</p>
<p>START SLAVE;</p>
<p>SHOW SLAVE STATUS\G;</p></blockquote>
<p>However, manually running this thousands of times was going to become tedius, so one of the team wrote a script to do it for us. It&#8217;ll automatically check that it&#8217;s only bypassing errors on a specific table (look out for &#8220;database.table&#8221; in the script), and bypass them all. It&#8217;s not perfect, but it seems to work pretty well. Here&#8217;s the code: <a rel="nofollow" href="http://pastie.org/private/mcxnw1oienrlfswciix4w">http://pastie.org/private/mcxnw1oienrlfswciix4w</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dancryer.com/2009/09/mysql-replication-issues/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
