MySQL HA:
1. Desirable – most of the time,
2. Needed – often enough,
3. Available – there are some good options out there.

Typical solutions consist of:
Heartbeat with DRBD on Linux. Although HB was introduced to Linux, it can be used on Solaris, FreeBSD and others without the DRBD but with other solutions.
Sun Cluster,
Veritas (commercial),
MySQL Proxy (still in alpha at the time of writing this blog but on testing proved to be a sweet solution),
Sequoia,
Tungsten (commercial),
MySQL cluster (which sadly doesn’t fit my scenario) and others

Whist researching the above list of load balancers / auto failover solutions I decided to give Sequoia (a load balancer and auto failover tier) a shot. I documented the commands and configuration steps and am listing them here under.
Used windows for this one (shameful I know :P) but should work the same on *nix.

After downloading and unzipping Sequoia I went ahead and configured the controller.xml file. Apart from several other parameters available, this is the place where you should set the port where sequoia listens to requests and forwards them to the MySQL instances it is configured to in return connect to.

------------------------------> CONTROLLER.XML to be stored in sequoia.x.xx/config/controller

<?xml version=”1.0″ encoding=”UTF-8″ ?>

<!DOCTYPE SEQUOIA-CONTROLLER PUBLIC “-//Continuent//DTD SEQUOIA-CONTROLLER 2.10.10//EN”  “http://sequoia.continuent.org/dtds/sequoia-controller-2.10.10.dtd”>

<SEQUOIA-CONTROLLER>
<Controller port=”25322″>
<Report hideSensitiveData=”true” generateOnShutdown=”true” generateOnFatal=”true” enableFileLogging=”true” />
<JmxSettings>
<RmiJmxAdaptor/>
</JmxSettings>
</Controller>
</SEQUOIA-CONTROLLER>

Next came the distribution file which contains several general parameters for which you should read the documentation if you would like to know better what each does. I personally followed a standard file and tuned it for my needs.

------------------------------> TEST-MYSQL-DISTRIBUTION.XML to be stored in sequoia.x.xx/config/virtualdatabase

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE SEQUOIA PUBLIC “-//Continuent//DTD SEQUOIA 2.10.10//EN” “http://sequoia.continuent.org/dtds/sequoia-2.10.10.dtd”>

<SEQUOIA>

<VirtualDatabase name=”test”>

<Monitoring>
<SQLMonitoring defaultMonitoring=”off”>
<SQLMonitoringRule queryPattern=”^select” caseSensitive=”false” applyToSkeleton =”false” monitoring=”on”/>
</SQLMonitoring>
</Monitoring>

<Backup>
<Backuper backuperName=”Octopus”
className=”org.continuent.sequoia.controller.backup.backupers.OctopusBackuper”
options=”zip=true”/>
</Backup>

<AuthenticationManager>
<Admin>
<User username=”admin” password=””/>
</Admin>
<VirtualUsers>
<VirtualLogin vLogin=”user” vPassword=””/>
</VirtualUsers>
</AuthenticationManager>

<DatabaseBackend name=”localhost1″ driver=”com.mysql.jdbc.Driver”
url=”jdbc:mysql://localhost:3306/test”
connectionTestStatement=”select 1″>
<ConnectionManager vLogin=”user” rLogin=”test” rPassword=””>
<VariablePoolConnectionManager initPoolSize=”10″ minPoolSize=”5″
maxPoolSize=”50″ idleTimeout=”30″ waitTimeout=”10″/>
</ConnectionManager>
</DatabaseBackend>

<DatabaseBackend name=”localhost2″ driver=”com.mysql.jdbc.Driver”
url=”jdbc:mysql://localhost:3307/test”
connectionTestStatement=”select 1″>
<ConnectionManager vLogin=”user” rLogin=”test” rPassword=””>
<VariablePoolConnectionManager initPoolSize=”10″ minPoolSize=”5″
maxPoolSize=”50″ idleTimeout=”30″ waitTimeout=”10″/>
</ConnectionManager>
</DatabaseBackend>

<RequestManager>
<RequestScheduler>
<RAIDb-1Scheduler level=”passThrough”/>
</RequestScheduler>

<RequestCache>
<MetadataCache/>
<ParsingCache/>
<!–       <ResultCache granularity=”table”/> –>
</RequestCache>

<LoadBalancer>
<RAIDb-1>
<WaitForCompletion policy=”first”/>
<RAIDb-1-LeastPendingRequestsFirst/>
</RAIDb-1>
</LoadBalancer>
<RecoveryLog driver=”com.mysql.jdbc.Driver”
url=”jdbc:mysql://localhost:3306/recovery” login=”test” password=””>
<RecoveryLogTable tableName=”RECOVERY”
logIdColumnType=”BIGINT NOT NULL”
vloginColumnType=”VARCHAR NOT NULL”
sqlColumnType=”VARCHAR NOT NULL”
extraStatementDefinition=”,PRIMARY KEY (log_id)”/>
<CheckpointTable tableName=”CHECKPOINT”
checkpointNameColumnType=”VARCHAR(255) NOT NULL”/>
<BackendTable tableName=”BACKEND”
databaseNameColumnType=”VARCHAR(255) NOT NULL”
backendNameColumnType=”VARCHAR(255) NOT NULL”
checkpointNameColumnType=”VARCHAR(255) NOT NULL”/>
<DumpTable tableName=”DUMP” dumpNameColumnType=”VARCHAR(255) NOT NULL”
dumpDateColumnType=”TIMESTAMP”
dumpPathColumnType=”VARCHAR(255) NOT NULL”
dumpFormatColumnType=”VARCHAR(255) NOT NULL”
checkpointNameColumnType=”VARCHAR(255) NOT NULL”
backendNameColumnType=”VARCHAR(255) NOT NULL”
tablesColumnType=”VARCHAR(255) NOT NULL”/>
</RecoveryLog>

</RequestManager>

</VirtualDatabase>

</SEQUOIA>

Given the above recovery log table contains illegal names for MySQL, it complains and therefore I went along and created the table directly using SQL. List of MySQL reserved words can be found here: http://dev.mysql.com/doc/mysqld-version-reference/en/mysqld-version-reference-reservedwords-5-1.html

------------------------------> INSTALLATION STEPS

1) Run the following create table before loading virtualdatabase configuration C:\test-mysql-distribution.xml on the console window:
CREATE DATABSE recovery

CREATE TABLE recovery (
`log_id` BIGINT NOT NULL UNIQUE,
`vlogin` TEXT NOT NULL,
`sql` VARCHAR(255) NOT NULL,
`sql_param` TEXT,
`auto_conn_tran` CHAR(1) NOT NULL,
`transaction_id` BIGINT,
`request_id` BIGINT,
`exec_status` CHAR(1) NOT NULL,
`exec_time` BIGINT,
`update_count` BIGINT,
PRIMARY KEY (`log_id`)
)

Edit controller.bat and console.bat to include the mysqlconnector in the CLASSPATH
SET CLASSPATH=;”C:\Program Files\sequoia-2.10.10-bin/drivers/mysql-connector-java-3.1.14-bin.jar”;$CLASSPATH

------------------------------> MySQL INSTALLATION STEPS

Install two mysql instances on 3306 and 3307 respectively, on the same machine (can be done on different machines and test-mysql-distribution.xml changed to suit the IPs. Set master – master replication and prepare startup / stop script. (For help installing master – master replication you can either use sandbox or install it customly using my.cnf replication settings and remember to set auto_increment_increment and auto_increment_offset according to how many masters you have.

On a two node setup they would be:

First Master the values:

auto_increment_increment = 2
auto_increment_offset = 1

Second Master:

auto_increment_increment = 2
auto_increment_offset = 2

If you are not knowledgable about the subject I recommend you use MySQL Sandbox or check out MySQL Documentation at: http://dev.mysql.com/doc/refman/5.1/en/replication.html

------------------------------> EXECUTION STEPS

Run controller.bat then console.bat and issue `load virtualdatabase configuration C:\test-mysql-distribution.xml` when ready

------------------------------> OUTPUT on CONSOLE.BAT window

NOTE if stuck in console, just hit `tab` and the commands will be displayed

Running the tools and software:

Launching the Sequoia controller console
Initializing Controller module...
Initializing VirtualDatabase Administration module...
Initializing SQL Console module...
Sequoia driver (Sequoia core v2.10.10) successfully loaded.
localhost:1090 > load virtualdatabase configuration C:\test-mysql-distribution.xml
XML file C:\test-mysql-distribution.xml successfully sent to Sequoia controller.
localhost:1090 > admin test
Virtual database Administrator Login > admin
Virtual database Administrator Password >
Ready to administrate virtual database test
test(admin) > initialize localhost1
Virtual Database test has been successfully initialized from backend localhost1
test(admin) > initialize localhost2
Backend localhost1 has a last known checkpoint (Initial_empty_recovery_log)
test(admin) > show backend localhost1
+--------------------------+----------------------------------+
| Backend Name | localhost1 |
| Driver | com.mysql.jdbc.Driver |
| URL | jdbc:mysql://localhost:3306/test |
| Active transactions | 0 |
| Pending Requests | 0 |
| Read Enabled | false |
| Write Enabled | false |
| Is Initialized | false |
| Static Schema | false |
| Connection Managers | 1 |
| Total Active Connections | 50 |
| Persistent Connections | 0 |
| Total Requests | 0 |
| Total Transactions | 0 |
| Last known checkpoint | Initial_empty_recovery_log |
+--------------------------+----------------------------------+

test(admin) > show backend localhost2
+--------------------------+----------------------------------+
| Backend Name | localhost2 |
| Driver | com.mysql.jdbc.Driver |
| URL | jdbc:mysql://localhost:3307/test |
| Active transactions | 0 |
| Pending Requests | 0 |
| Read Enabled | false |
| Write Enabled | false |
| Is Initialized | false |
| Static Schema | false |
| Connection Managers | 1 |
| Total Active Connections | 50 |
| Persistent Connections | 0 |
| Total Requests | 0 |
| Total Transactions | 0 |
| Last known checkpoint | |
+--------------------------+----------------------------------+

test(admin) > enable localhost1 force
Enabling backend localhost1 from its last known checkpoint
test(admin) > show backend localhost1
+--------------------------+----------------------------------+
| Backend Name | localhost1 |
| Driver | com.mysql.jdbc.Driver |
| URL | jdbc:mysql://localhost:3306/test |
| Active transactions | 0 |
| Pending Requests | 0 |
| Read Enabled | true |
| Write Enabled | true |
| Is Initialized | true |
| Static Schema | false |
| Connection Managers | 1 |
| Total Active Connections | 10 |
| Persistent Connections | 0 |
| Total Requests | 0 |
| Total Transactions | 0 |
| Last known checkpoint | |
+--------------------------+----------------------------------+

test(admin) > initialize localhost2 force
Virtual Database test has been successfully initialized from backend localhost2
test(admin) > enable localhost2
Enabling backend localhost2 from its last known checkpoint
test(admin) > show backend localhost1
+--------------------------+--------------------------------------------------------------+
| Backend Name | localhost1 |
| Driver | com.mysql.jdbc.Driver |
| URL | jdbc:mysql://localhost:3306/test |
| Active transactions | 0 |
| Pending Requests | 0 |
| Read Enabled | false |
| Write Enabled | false |
| Is Initialized | false |
| Static Schema | false |
| Connection Managers | 2 |
| Total Active Connections | 25 |
| Persistent Connections | 0 |
| Total Requests | 0 |
| Total Transactions | 0 |
| Last known checkpoint | backup localhost1-172.22.16.103:25322-20090311114054271+0000 |
+--------------------------+--------------------------------------------------------------+

test(admin) > disable localhost1
Disabling backend localhost1 with automatic checkpoint.
test(admin) > initialize localhost1 force
Virtual Database test has been successfully initialized from backend localhost1
test(admin) > enable localhost1
Enabling backend localhost1 from its last known checkpoint
test(admin) > show backend localhost1
+--------------------------+----------------------------------+
| Backend Name | localhost1 |
| Driver | com.mysql.jdbc.Driver |
| URL | jdbc:mysql://localhost:3306/test |
| Active transactions | 0 |
| Pending Requests | 0 |
| Read Enabled | true |
| Write Enabled | true |
| Is Initialized | true |
| Static Schema | false |
| Connection Managers | 2 |
| Total Active Connections | 30 |
| Persistent Connections | 0 |
| Total Requests | 0 |
| Total Transactions | 0 |
| Last known checkpoint | |
+--------------------------+----------------------------------+

test(admin) > show backend localhost2
+--------------------------+----------------------------------+
| Backend Name | localhost2 |
| Driver | com.mysql.jdbc.Driver |
| URL | jdbc:mysql://localhost:3307/test |
| Active transactions | 0 |
| Pending Requests | 0 |
| Read Enabled | true |
| Write Enabled | true |
| Is Initialized | true |
| Static Schema | false |
| Connection Managers | 2 |
| Total Active Connections | 25 |
| Persistent Connections | 0 |
| Total Requests | 3 |
| Total Transactions | 0 |
| Last known checkpoint | |
+--------------------------+----------------------------------+

test(admin) > show backend localhost2
+--------------------------+----------------------------------+
| Backend Name | localhost2 |
| Driver | com.mysql.jdbc.Driver |
| URL | jdbc:mysql://localhost:3307/test |
| Active transactions | 0 |
| Pending Requests | 0 |
| Read Enabled | true |
| Write Enabled | true |
| Is Initialized | true |
| Static Schema | false |
| Connection Managers | 2 |
| Total Active Connections | 25 |
| Persistent Connections | 0 |
| Total Requests | 3 |
| Total Transactions | 0 |
| Last known checkpoint | |
+--------------------------+----------------------------------+

test(admin) > disable localhost2
Disabling backend localhost2 with automatic checkpoint.
test(admin) > initialize localhost2 force
Virtual Database test has been successfully initialized from backend localhost2
test(admin) > enable localhost2
Enabling backend localhost2 from its last known checkpoint
test(admin) > disable localhost1
Disabling backend localhost1 with automatic checkpoint.
test(admin) > initialize localhost1
Backend localhost2 is not in a disabled state (current state is enabled)
test(admin) > disable localhost1
Disabling backend localhost1 with automatic checkpoint.
test(admin) > initialize localhost1
Backend localhost2 is not in a disabled state (current state is enabled)
test(admin) > initialize localhost1 force
Virtual Database test has been successfully initialized from backend localhost1
test(admin) > enable localhost1
Enabling backend localhost1 from its last known checkpoint
test(admin) >



------------------------------> OUTPUT on CMD JAVA PROCESS EXECUTION WINDOW

C:\Program Files\MySQL>java -cp .;"c:\Program Files\MySQL\sequoia-driver.jar" Connect
Database connection established
id = 2, name = snake, category = reptile
id = 4, name = frog, category = amphibian
id = 6, name = tuna, category = fish
id = 8, name = racoon, category = mammal
4 rows were retrieved
Database connection terminated



-------------------------------> Here I inserted some rows directly in the database and reran the java program


C:\Program Files\MySQL>java -cp .;"c:\Program Files\MySQL\sequoia-driver.jar" Connect
Database connection established
id = 2, name = snake, category = reptile
id = 4, name = frog, category = amphibian
id = 6, name = tuna, category = fish
id = 8, name = racoon, category = mammal
id = 10, name = darren, category = human
id = 12, name = michael, category = alien
6 rows were retrieved
Database connection terminated



------------------------------> The JAVA PROGRAM used, obtained from: http://www.kitebird.com/articles/jdbc.html :


import java.sql.*;

public class Connect
{
public static void main (String[] args)
{
Connection conn = null;

try
{
String userName = "admin";
String password = "";
String url = "jdbc:sequoia://127.0.0.1:25322/test?user=root";
Class.forName ("org.continuent.sequoia.driver.Driver").newInstance ();
conn = DriverManager.getConnection (url,userName,password);
System.out.println ("Database connection established");

/* Uncomment the following at the first run so that it creates a table called animal and inserts a few rows in it.
*/
/* Statement s = conn.createStatement ();
int count;
s.executeUpdate ("DROP TABLE IF EXISTS animal");
s.executeUpdate (
"CREATE TABLE animal ("
+ "id INT UNSIGNED NOT NULL AUTO_INCREMENT,"
+ "PRIMARY KEY (id),"
+ "name CHAR(40), category CHAR(40))");
count = s.executeUpdate (
"INSERT INTO animal (name, category)"
+ " VALUES"
+ "('snake', 'reptile'),"
+ "('frog', 'amphibian'),"
+ "('tuna', 'fish'),"
+ "('racoon', 'mammal')");
s.close ();
System.out.println (count + " rows were inserted"); : */

Statement s = conn.createStatement ();
s.executeQuery ("SELECT id, name, category FROM animal");
ResultSet rs = s.getResultSet ();
int count = 0;
while (rs.next ())
{
int idVal = rs.getInt ("id");
String nameVal = rs.getString ("name");
String catVal = rs.getString ("category");
System.out.println (
"id = " + idVal
+ ", name = " + nameVal
+ ", category = " + catVal);
++count;
}
rs.close ();
s.close ();
System.out.println (count + " rows were retrieved");



}
catch (Exception e)
{
System.err.println ("Cannot connect to database server");
// System.err.println (e);
e.printStackTrace();
}
finally
{
if (conn != null)
{
try
{
conn.close ();
System.out.println ("Database connection terminated");
}
catch (Exception e) { /* ignore close errors */ }
}
}
}
}



------------------------------> COMPILING / EXECUTING JAVA PROGRAM

download and install JDK
compile: javac Connect.java
execute: java -cp .;”c:\Program Files\MySQL\sequoia-driver.jar” Connect

VN:F [1.9.22_1171]
Rating: 7.0/10 (2 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

MySQL HA – Let’s take a look at Sequoia, 7.0 out of 10 based on 2 ratings

*