Saturday, April 28, 2007

NDB/J - A direct Java API to MySQL Cluster

YOU SHOULD USE NDB/BINDINGS WHICH YOU CAN FIND HERE! NDB/BINDINGS IS THE OFFICIAL VERSION BEING MAINTAINED AND INCLUDES NDB/J.

IGNORE EVERYTHING BELOW THIS POINT (except the first couple of sentences):

NDB/J is a type II Java connector that makes it possible for a Java application to connect directly to the NDBCluster storage engine, thus by-passing the MySQL Server.
Initial benchmarks we have conducted shows that NDB/J is in parity with the C++ NDBAPI when it comes to performance. Moreover, NDB/J is a wrapper of the C++ NDBAPI, but offers Java-like abstractions such as Exceptions and ResultSets.

If you are interested in evaluating NDB/J and trying it out, you can download it here.
The following versions of MySQL Cluster should work:
  • MySQL Cluster 5.0.x
  • MySQL Cluster 5.1.16 and above, an interface change prohibits earlier releases from compiling ndb/j.

Documentation will also be put there, but it is also possible to generate the documentation using Javadoc from the source code.

There is also a mailing list, which you can use:
ndb-j@lists.mysql.com
Register here and scroll down to NDB/J and press "subscribe".
MySQL offers no support for NDB/J at this stage, but we will try to help you as fast as possible on the mailing lists and you can also get help from Professional Services at MySQL.

Below you will find a simple test program and how to get going! Good luck!


Quick start

Here is a quick start for how to get going:
  1. Install MySQL Cluster 5.0 or 5.1, you need it on the same computer as from which you will compile NDB/J.
  2. Download ndb/j and untar it.
  3. export JAVA_HOME=/path/to/java/
  4. ./configure --with-mysql=/path/to/mysql/ --prefix=/path/to/mysql
    1. --prefix = where ndb/j libraries will be installed
    2. --with-mysql = where mysql is installed
  5. make
  6. make install
    1. this installs mysql-ndbj-0.1.jar and libndbj.so in the "--prefix" directory
In the docs directory you will also get Javadoc documentation for ndb/j and mgm/j (which is a wrapper of the management API, MGMAPI).

We have tested this mostly on 32-bit Linux and Sun JDK 1.5 and 1.6, gcc 3.3.6 (ubuntu) and g++ 3.3.6 (ubuntu). Please let us know on ndb-j@lists.mysql if you have problems compiling on your particular Linux platform. And yes, we have some work to do on the build system :)

Simple example program
Cut this and paste it into "Test.java" (and sorry for the indentation):


import com.mysql.storage.ndb.ndbapi.*;


/*
create table t1(a integer primary key,
b char(32), c varchar(255), d bigint) engine=ndb;

This program inserts and reads a row form this table.

*/

class Test
{
public static void main(String args[])
{

System.loadLibrary("ndbj");
NdbClusterConnection conn=null;
Ndb ndb=null;

try
{

/**
* Connect to MySQL Cluster
* 1). Connect to management server (localhost in this case)
* 2). Connect to the data nodes (waitUntilReady)
*/
conn = NdbFactory.createNdbClusterConnection("localhost");
conn.connect(5,3,true);
conn.waitUntilReady(30,0);

/**
* Get a connection to NDB (once / thread)
*/
ndb = conn.createNdb("test",false);
ndb.init(1000);



/*
* INSERT EXAMPLE
* INSERT INTO t1 VALUES(1,"hello", "ndb/j", 20070428);
*/

/*
* define what to insert:
*/

int a=1;
String b="hello";
String c="ndb/j";
long d = 20070428;

NdbTransaction t=null;
NdbOperation op=null;

t = ndb.startTransaction();


op = t.getNdbOperation("t1");
op.insertTuple();
op.setInt( "a", a);
op.setString("b", b ); //char
op.setString("c", c ); //varchar
op.setLong("d", d ); //bigint

t.execute(NdbTransaction.ExecType.Commit,
NdbTransaction.AbortOption.AbortOnError,
true);

/*
* MUST CLOSE TRANSACTION WHEN DONE WITH IT
* ELSE IT WILL FAIL LATER
* AT SOME STAGE!!
*/
t.close();



/**
* READ EXAMPLE - implements:
* SELECT * FROM t1 WHERE a = 1;
*/

int read_pk_a = 1; //pk to read


NdbResultSet rs = null;

t = ndb.startTransaction();

op = t.getNdbOperation("t1");
op.committedRead();
op.equal( "a", read_pk_a);
op.getValue("b");
op.getValue("c");
op.getValue("d");
rs =op.resultData();

t.execute(NdbTransaction.ExecType.NoCommit,
NdbTransaction.AbortOption.AbortOnError,
true);

while(rs.next())
{
System.out.println("a= " + read_pk_a +
"\nb= " + rs.getString("b") +
"\nc= " + rs.getString("c") +
"\nd= " + rs.getLong("d"));
}
/*
* MUST CLOSE TRANSACTION WHEN DONE WITH IT
* ELSE IT WILL FAIL LATER
* AT SOME STAGE!!
*/
t.close();

}
catch (NdbClusterConnectionPermanentException e) {
// Serious problem. Retrying connecting will not work.
}
catch (NdbClusterConnectionTemporaryException e) {
// We can retry connecting if we catch this exception
}
catch (NdbApiException e)
{
System.out.println("NdbAPI exception= " + e.getMessage());

}
catch(Exception e)
{
System.out.println("exception= " + e.getMessage());
}
finally {
if (conn != null)
conn.close();
}
}
}


Compiling and running example program
Please note that you need to have a running MySQL Cluster to run this program.
  1. export CLASSPATH=/path/mysql-ndbj-0.1.jar:.
  2. export LD_LIBRARY_PATH=/path where libndbj.so is/:$LD_LIBRARY_PATH
  3. javac Test.java
  4. mysql -u root
    1. mysql> use test;
    2. create table t1(a integer primary key,
      b char(32), c varchar(255), d bigint) engine=ndb;
  5. java Test
Congratulations!