Table of Contents
Abstract
This chapter discusses preparations for writing an
NDB API application.
Abstract
This section provides information on compiling and linking
NDB API applications, including requirements
and compiler and linker options.
To use the NDB API with MySQL, you must have
the NDB client library and its header files
installed alongside the regular MySQL client libraries and
headers. These are automatically installed when you build MySQL
using the --with-ndbcluster
configure option or when using a MySQL binary
package that supports the NDBCluster storage
engine.
MySQL 4.1 does not install the required
NDB-specific header files. You should use
MySQL 5.0 or later when writing NDB API
applications, and this Guide is targeted for use with MySQL
5.1.
Header Files.
In order to compile source files that use the
NDB API, you must ensure that the necessary
header files can be found. Header files specific to the
NDB API are installed in the following
subdirectories of the MySQL include
directory:
include/mysql/storage/ndb/ndbapi
include/mysql/storage/ndb/mgmapi
Compiler Flags. The MySQL-specific compiler flags needed can be determined using the mysql_config utility that is part of the MySQL installation:
$ mysql_config --cflags -I/usr/local/mysql/include/mysql -Wreturn-type -Wtrigraphs -W -Wformat -Wsign-compare -Wunused -mcpu=pentium4 -march=pentium4
This sets the include path for the MySQL header files but not
for those specific to the NDB API. The
--include option to
mysql_config returns the generic include
path switch:
shell> mysql_config --include -I/usr/local/mysql/include/mysql
It is necessary to add the subdirectory paths explicitly, so
that adding all the needed compile flags to the
CXXFLAGS shell variable should look
something like this:
CFLAGS="$CFLAGS "`mysql_config --cflags` CFLAGS="$CFLAGS "`mysql_config --include`storage/ndb CFLAGS="$CFLAGS "`mysql_config --include`storage/ndb/ndbapi CFLAGS="$CFLAGS "`mysql_config --include`storage/ndb/mgmapi
If you do not intend to use the Cluster management functions,
the last line in the previous example can be omitted. However,
if you are interested in the management functions only, and do
not want or need to access Cluster data except from MySQL,
then you can omit the line referencing the
ndbapi directory.
NDB API applications must be linked against
both the MySQL and NDB client libraries. The
NDB client library also requires some
functions from the mystrings library, so this
must be linked in as well.
The necessary linker flags for the MySQL client library are
returned by mysql_config
--libs. For multithreaded
applications you should use the --libs_r
instead:
$ mysql_config --libs_r -L/usr/local/mysql-5.1/lib/mysql -lmysqlclient_r -lz -lpthread -lcrypt -lnsl -lm -lpthread -L/usr/lib -lssl -lcrypto
To link an NDB API application, it is necessary to add
-lndbclient and -lmystrings to
these options. Adding all the required linker flags to the
LDFLAGS variable should look something like
this:
LDFLAGS="$LDFLAGS "`mysql_config --libs_r` LDFLAGS="$LDFLAGS -lndbclient -lmystrings"
It is often faster and simpler to use GNU autotools than to
write your own makefiles. In this section, we provide an
autoconf macro WITH_MYSQL that can be used to
add a --with-mysql option to a configure file,
and that automatically sets the correct compiler and linker
flags for given MySQL installation.
All of the examples in this chapter include a common
mysql.m4 file defining
WITH_MYSQL. A typical complete example
consists of the actual source file and the following helper
files:
acinclude
configure.in
Makefile.m4
automake also requires that you provide
README, NEWS,
AUTHORS, and ChangeLog
files; however, these can be left empty.
To create all necessary build files, run the following:
aclocal
autoconf
automake -a -c
configure --with-mysql=/mysql/prefix/path
Normally, this needs to be done only once, after which make will accommodate any file changes.
Example 1-1: acinclude.m4.
m4_include([../mysql.m4])
Example 1-2: configure.in.
AC_INIT(example, 1.0) AM_INIT_AUTOMAKE(example, 1.0) WITH_MYSQL() AC_OUTPUT(Makefile)
Example 1-3: Makefile.am.
bin_PROGRAMS = example example_SOURCES = example.cc
Example 1-4: WITH_MYSQL source for inclusion in
acinclude.m4.
dnl
dnl configure.in helper macros
dnl
AC_DEFUN([WITH_MYSQL], [
AC_MSG_CHECKING(for mysql_config executable)
AC_ARG_WITH(mysql, [ --with-mysql=PATH path to mysql_config binary or mysql prefix dir], [
if test -x $withval -a -f $withval
then
MYSQL_CONFIG=$withval
elif test -x $withval/bin/mysql_config -a -f $withval/bin/mysql_config
then
MYSQL_CONFIG=$withval/bin/mysql_config
fi
], [
if test -x /usr/local/mysql/bin/mysql_config -a -f /usr/local/mysql/bin/mysql_config
then
MYSQL_CONFIG=/usr/local/mysql/bin/mysql_config
elif test -x /usr/bin/mysql_config -a -f /usr/bin/mysql_config
then
MYSQL_CONFIG=/usr/bin/mysql_config
fi
])
if test "x$MYSQL_CONFIG" = "x"
then
AC_MSG_RESULT(not found)
exit 3
else
AC_PROG_CC
AC_PROG_CXX
# add regular MySQL C flags
ADDFLAGS=`$MYSQL_CONFIG --cflags`
# add NDB API specific C flags
IBASE=`$MYSQL_CONFIG --include`
ADDFLAGS="$ADDFLAGS $IBASE/ndb"
ADDFLAGS="$ADDFLAGS $IBASE/ndb/ndbapi"
ADDFLAGS="$ADDFLAGS $IBASE/ndb/mgmapi"
CFLAGS="$CFLAGS $ADDFLAGS"
CXXFLAGS="$CXXFLAGS $ADDFLAGS"
LDFLAGS="$LDFLAGS "`$MYSQL_CONFIG --libs_r`" -lndbclient -lmystrings"
AC_MSG_RESULT($MYSQL_CONFIG)
fi
])
Abstract
This section covers connecting an NDB API
application to a MySQL cluster.
NDB API applications require one or more of
the following include files:
Applications accessing Cluster data via the
NDB API must include the file
NdbApi.hpp.
Applications making use of both the NDB
API and the regular MySQL client API also need to include
mysql.h.
Applications that use cluster management functions need
the include file mgmapi.h.
Before using the NDB API, it must first be
initialised by calling the ndb_init()
function. Once an NDB API application is
complete, call ndb_end(0) to perform a
cleanup.
To establish a connection to the server, it is necessary to
create an instance of Ndb_cluster_connection,
whose constructor takes as its argument a cluster connectstring;
if no connectstring is given, localhost is
assumed.
The cluster connection is not actually initiated until the
Ndb_cluster_connection::connect() method is
called. When invoked without any arguments, the connection
attempt is retried each 1 second indefinitely until successful,
and no reporting is done. See
Section 3.2, “The Ndb_cluster_connection Class”, for details.
By default an API node will connect to the
“nearest” data node — usually a data node
running on the same machine, due to the fact that shared memory
transport can be used instead of the slower TCP/IP. This may
lead to poor load distribution in some cases, so it is possible
to enforce a round-robin node connection scheme by calling the
set_optimized_node_selection() method with
0 as its argument prior to calling
connect(). (See
Section 3.2.1.4, “Ndb_cluster_connection::set_optimized_node_selection()”.)
The connect() method initiates a connection
to a cluster management node only — it does not wait for
any connections to data nodes to be made. This can be
accomplished by using wait_until_ready()
after calling connect(). The
wait_until_ready() method waits up to a given
number of seconds for a connection to a data node to be
established.
In the following example, initialisation and connection are
handled in the two functions example_init()
and example_end(), which will be included in
subsequent examples via the file
example_connection.h.
Example 2-1: Connection example.
#include <stdio.h>
#include <stdlib.h>
#include <NdbApi.hpp>
#define CONNECTSTR "localhost"
Ndb_cluster_connection* example_init()
{
Ndb_cluster_connection* conn;
// initialise MySQL and Ndb client libraries
if( ndb_init() )
{
exit(EXIT_FAILURE);
}
// prepare connection to cluster
conn = new Ndb_cluster_connection(CONNECTSTR);
// initiate connection
if( conn->connect(4, 5, 1) )
{
fprintf(stderr, "Unable to connect to cluster within 30 seconds.");
exit(EXIT_FAILURE);
}
// wait for data (ndbd) nodes
if(conn->wait_until_ready(30, 0) < 0)
{
fprintf(stderr, "Cluster was not ready within 30 seconds.\n");
exit(EXIT_FAILURE);
}
return conn;
}
void example_end(Ndb_cluster_connection* conn)
{
// terminate connection
delete conn;
// shut down MySQL and Ndb client libraries
ndb_end(2);
}
int main(int argc, char** argv)
{
Ndb_cluster_connection* conn;
conn = example_connect();
printf("Connection established.");
example_end(conn);
return EXIT_SUCCESS;
}
Abstract
This section discusses NDB naming and other conventions with regard to database objects.
Databases and Schemas.
Databases and schemas are not represented by objects as such in
the NDB API. Instead, they are modelled as
attributes of Table and
Index objects. The value of the
database attribute of one of these objects is
always the same as the name of the MySQL database to which the
table or index belongs. The value of the
schema attribute of a
Table or Index object is
always 'def' (for “default”).
Tables.
MySQL table names are directly mapped to NDB
table names without modification. Table names starting with
'NDB$' are reserved for internal use>, as is
the SYSTAB_0 table in the
sys database.
Indexes. There are two different type of NDB indexes:
Hash indexes are unique, but not ordered.
B-tree indexes are ordered, but allow duplicate values.
Names of unique indexes and primary keys are handled as follows:
For a MySQL UNIQUE index, both a B-tree
and a hash index are created. The B-tree index uses the
MySQL name for the index; the name for the hash index is
generated by appending '$unique' to the
index name.
For a MySQL primary key only a B-tree index is created.
This index is given the name PRIMARY.
There is no extra hash; however, the uniqueness of the
primary key is guaranteed by making the MySQL key the
internal primary key of the NDB table.
Column Names and Values.
NDB column names are the same as their MySQL
names.
Datatypes.
MySQL datatypes are stored in NDB columns as
follows:
The MySQL TINYINT,
SMALLINT, INT, and
BIGINT datatypes map to
NDB types having the same names and
storage requirements as their MySQL counterparts.
The MySQL FLOAT and
DOUBLE datatypes are mapped to
NDB types having the same names and
storage requirements.
The storage space required for a MySQL
CHAR column is determined by the
maximum number of characters and the column's character
set. For most (but not all) character sets, each character
takes one byte of storage. When using UTF-8, each
character requires three bytes. You can find the number of
bytes needed per character in a given character set by
checking the Maxlen column in the
output of SHOW CHARACTER SET.
In MySQL 5.1, the storage requirements for a
VARCHAR or VARBINARY
column depend on whether the column is stored in memory or
on disk:
For in-memory columns, the
NDBCLUSTER storage engine
supports variable-width columns with 4-byte
alignment. This means that (for example) a the
string 'abcde' stored in a
VARCHAR(50) column using the
latin1 character set requires 12
bytes — in this case, 2 bytes times 5
characters is 10, rounded up to the next even
multiple of 4 yields 12. (This represents a change
in behaviour from Cluster in MySQL 5.0 and 4.1,
where a column having the same definition required
52 bytes storage per row regardless of the length of
the string being stored in the row.)
In Disk Data columns, VARCHAR and
VARBINARY are stored as
fixed-width columns. This means that each of these
types requires the same amount of storage as a
CHAR of the same size.
Each row in a Cluster BLOB or
TEXT column is made up of two separate
parts. One of these is of fixed size (256 bytes), and is
actually stored in the original table. The other consists
of any data in excess of 256 bytes, which stored in a
hidden table. The rows in this second table are always
2000 bytes long. This means that record of
size bytes in a
TEXT or BLOB column
requires
256 bytes, if
size <=
256
256 + 2000 *
(( bytes otherwise
size – 256) \ 2000) +
1)