Finally, sane MySQL clustering
This commit is contained in:
91
2006-01-24-finally-sane-mysql-clustering.html
Normal file
91
2006-01-24-finally-sane-mysql-clustering.html
Normal file
@@ -0,0 +1,91 @@
|
||||
<!--# set var="title" value="Finally, sane MySQL clustering" -->
|
||||
<!--# set var="date" value="January 24, 2006" -->
|
||||
|
||||
<!--# include file="include/top.html" -->
|
||||
|
||||
<p>As of MySQL 5.1.5, we’ve finally got <a href="http://dev.mysql.com/doc/refman/5.1/en/replication-row-based.html">row-based replication</a>. This is the last piece of the puzzle to make circular replication usable. Here’s how:</p>
|
||||
|
||||
<p>I’m assuming two MySQL servers, A and B. You can, however, use as many as you want, as long as they all somehow pull the logs from all the others.</p>
|
||||
|
||||
<p>Set the following config variables on both servers:</p>
|
||||
|
||||
<pre><code>server-id=<unique number per server>
|
||||
log-bin=<hostname>-bin
|
||||
relay-log=<hostname>-bin
|
||||
log-slave-updates # really only necessary in circular replication > 2 servers
|
||||
binlog-format=row
|
||||
</code></pre>
|
||||
|
||||
<p>Using the MySQL client, create replication users on both servers:</p>
|
||||
|
||||
<pre><code>GRANT REPLICATION SLAVE ON *.* TO repl@’%’ IDENTIFIED BY ‘<password>’;
|
||||
</code></pre>
|
||||
|
||||
<p>Then set master information on both servers, start replication and check that it’s working:</p>
|
||||
|
||||
<pre><code>CHANGE MASTER TO MASTER_HOST=’<address of other server>‘, MASTER_USER=’repl’, MASTER_PASSWORD=’<password>‘;
|
||||
START SLAVE;
|
||||
SHOW SLAVE STATUS\G
|
||||
</code></pre>
|
||||
|
||||
<p>You should now be able to see multi-master replication in action:</p>
|
||||
|
||||
<p>On A:</p>
|
||||
|
||||
<pre><code>CREATE DATABASE repl_test;
|
||||
SHOW DATABASES;
|
||||
</code></pre>
|
||||
|
||||
<p>On B:</p>
|
||||
|
||||
<pre><code>SHOW DATABASES;
|
||||
DROP DATABASE repl_test;
|
||||
SHOW DATABASES;
|
||||
</code></pre>
|
||||
|
||||
<p>On A:</p>
|
||||
|
||||
<pre><code>SHOW DATABASES;
|
||||
</code></pre>
|
||||
|
||||
<h3>The AUTO_INCREMENT problem</h3>
|
||||
|
||||
<p>AUTO_INCREMENT-type columns get used in just about every MySQL table. They’re a quick way to build primary keys without thinking. However, there are obvious problems in a multi-master setup (if inserts happen on both servers at the same time, they’ll both get the same ID). The official MySQL solution (start the IDs on both servers at numbers significantly different from each other) is a nasty hack.</p>
|
||||
|
||||
<p>However, we’ve had <a href="http://dev.mysql.com/doc/refman/5.1/en/triggers.html">triggers</a> in InnoDB tables since MySQL 5.0, and with row-level replication, handy functions like <a href="http://dev.mysql.com/doc/refman/5.1/en/miscellaneous-functions.html#id2906147">UUID()</a> now replicate properly. This gives us a neat solution. On A:</p>
|
||||
|
||||
<pre><code>CREATE DATABASE IF NOT EXISTS test;
|
||||
USE test;
|
||||
CREATE TABLE repl_test (id CHAR(36) BINARY, test INT) ENGINE=InnoDB;
|
||||
|
||||
delimiter //
|
||||
|
||||
CREATE TRIGGER repl_test_before_insert BEFORE INSERT ON repl_test FOR EACH ROW
|
||||
BEGIN
|
||||
IF NEW.id IS NULL THEN
|
||||
SET NEW.id = UUID();
|
||||
END IF;
|
||||
SET @repl_test_last_insert_id = NEW.id;
|
||||
END
|
||||
//
|
||||
|
||||
delimiter ;
|
||||
|
||||
INSERT INTO repl_test SET test=5;
|
||||
SELECT * FROM repl_test;
|
||||
SELECT @repl_test_last_insert_id;
|
||||
</code></pre>
|
||||
|
||||
<p>On B:</p>
|
||||
|
||||
<pre><code>SELECT * FROM repl_test;
|
||||
INSERT INTO repl_test SET test=6;
|
||||
SELECT * FROM repl_test;
|
||||
</code></pre>
|
||||
|
||||
<p>On A:</p>
|
||||
|
||||
<pre><code>SELECT * FROM repl_test;
|
||||
</code></pre>
|
||||
|
||||
<!--# include file="include/bottom.html" -->
|
||||
@@ -40,6 +40,7 @@
|
||||
<li>2009-Sep-11: <a href="2009-09-11-confusing-bind-with-cnames.html">Confusing BIND with CNAMEs</a></li>
|
||||
<li>2009-Feb-19: <a href="2019-02-19-the-odd-case-of-my-mugging.html">The odd case of my mugging</a></li>
|
||||
<li>2009-Feb-03: <a href="2009-02-03-5-packet-tcp-connection.html">5-packet TCP connection?</a></li>
|
||||
<li>2006-Jan-24: <a href="2006-01-24-finally-sane-mysql-clustering.html">Finally, sane MySQL clustering</a></li>
|
||||
<li>2006-Jan-23: <a href="2006-01-23-ibm-thinkcentre-a50-slowdown.html">IBM ThinkCentre A50 Slowdown</a></li>
|
||||
<li>2006-Jan-23: <a href="2006-01-23-ssh-tunnelling-101.html">SSH Tunnelling 101</a></li>
|
||||
<li>2006-Jan-23: <a href="2006-01-23-how-to-install-debian-sarge-on-an-ibm-blade.html">How to install Debian Sarge on an IBM Blade</a></li>
|
||||
|
||||
82
markdown/2006-01-24-finally-sane-mysql-clustering.md
Normal file
82
markdown/2006-01-24-finally-sane-mysql-clustering.md
Normal file
@@ -0,0 +1,82 @@
|
||||
<!--# set var="title" value="Finally, sane MySQL clustering" -->
|
||||
<!--# set var="date" value="January 24, 2006" -->
|
||||
|
||||
<!--# include file="include/top.html" -->
|
||||
|
||||
As of MySQL 5.1.5, we’ve finally got [row-based replication](http://dev.mysql.com/doc/refman/5.1/en/replication-row-based.html). This is the last piece of the puzzle to make circular replication usable. Here’s how:
|
||||
|
||||
I’m assuming two MySQL servers, A and B. You can, however, use as many as you want, as long as they all somehow pull the logs from all the others.
|
||||
|
||||
Set the following config variables on both servers:
|
||||
|
||||
server-id=<unique number per server>
|
||||
log-bin=<hostname>-bin
|
||||
relay-log=<hostname>-bin
|
||||
log-slave-updates # really only necessary in circular replication > 2 servers
|
||||
binlog-format=row
|
||||
|
||||
Using the MySQL client, create replication users on both servers:
|
||||
|
||||
GRANT REPLICATION SLAVE ON *.* TO repl@’%’ IDENTIFIED BY ‘<password>’;
|
||||
|
||||
Then set master information on both servers, start replication and check that it’s working:
|
||||
|
||||
CHANGE MASTER TO MASTER_HOST=’<address of other server>‘, MASTER_USER=’repl’, MASTER_PASSWORD=’<password>‘;
|
||||
START SLAVE;
|
||||
SHOW SLAVE STATUS\G
|
||||
|
||||
You should now be able to see multi-master replication in action:
|
||||
|
||||
On A:
|
||||
|
||||
CREATE DATABASE repl_test;
|
||||
SHOW DATABASES;
|
||||
|
||||
On B:
|
||||
|
||||
SHOW DATABASES;
|
||||
DROP DATABASE repl_test;
|
||||
SHOW DATABASES;
|
||||
|
||||
On A:
|
||||
|
||||
SHOW DATABASES;
|
||||
|
||||
### The AUTO\_INCREMENT problem
|
||||
|
||||
AUTO\_INCREMENT-type columns get used in just about every MySQL table. They’re a quick way to build primary keys without thinking. However, there are obvious problems in a multi-master setup (if inserts happen on both servers at the same time, they’ll both get the same ID). The official MySQL solution (start the IDs on both servers at numbers significantly different from each other) is a nasty hack.
|
||||
|
||||
However, we’ve had [triggers](http://dev.mysql.com/doc/refman/5.1/en/triggers.html) in InnoDB tables since MySQL 5.0, and with row-level replication, handy functions like [UUID()](http://dev.mysql.com/doc/refman/5.1/en/miscellaneous-functions.html#id2906147) now replicate properly. This gives us a neat solution. On A:
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS test;
|
||||
USE test;
|
||||
CREATE TABLE repl_test (id CHAR(36) BINARY, test INT) ENGINE=InnoDB;
|
||||
|
||||
delimiter //
|
||||
|
||||
CREATE TRIGGER repl_test_before_insert BEFORE INSERT ON repl_test FOR EACH ROW
|
||||
BEGIN
|
||||
IF NEW.id IS NULL THEN
|
||||
SET NEW.id = UUID();
|
||||
END IF;
|
||||
SET @repl_test_last_insert_id = NEW.id;
|
||||
END
|
||||
//
|
||||
|
||||
delimiter ;
|
||||
|
||||
INSERT INTO repl_test SET test=5;
|
||||
SELECT * FROM repl_test;
|
||||
SELECT @repl_test_last_insert_id;
|
||||
|
||||
On B:
|
||||
|
||||
SELECT * FROM repl_test;
|
||||
INSERT INTO repl_test SET test=6;
|
||||
SELECT * FROM repl_test;
|
||||
|
||||
On A:
|
||||
|
||||
SELECT * FROM repl_test;
|
||||
|
||||
<!--# include file="include/bottom.html" -->
|
||||
@@ -39,6 +39,7 @@
|
||||
1. 2009-Sep-11: [Confusing BIND with CNAMEs](2009-09-11-confusing-bind-with-cnames.html)
|
||||
1. 2009-Feb-19: [The odd case of my mugging](2019-02-19-the-odd-case-of-my-mugging.html)
|
||||
1. 2009-Feb-03: [5-packet TCP connection?](2009-02-03-5-packet-tcp-connection.html)
|
||||
1. 2006-Jan-24: [Finally, sane MySQL clustering](2006-01-24-finally-sane-mysql-clustering.html)
|
||||
1. 2006-Jan-23: [IBM ThinkCentre A50 Slowdown](2006-01-23-ibm-thinkcentre-a50-slowdown.html)
|
||||
1. 2006-Jan-23: [SSH Tunnelling 101](2006-01-23-ssh-tunnelling-101.html)
|
||||
1. 2006-Jan-23: [How to install Debian Sarge on an IBM Blade](2006-01-23-how-to-install-debian-sarge-on-an-ibm-blade.html)
|
||||
|
||||
Reference in New Issue
Block a user