MariaDB non-blocking client API and node.js

Last Summer I implemented a non-blocking client API in MariaDB, and it was included in the MariaDB 5.5 release. But somehow I never got around to announcing it.

However, that did not prevent Brian White from noticing it, and using it to implement a new mysql binding for node.js called mariasql.

Now, node.js is a single-threaded, event-driven framework for web application sever development. In such frameworks, all I/O is done non-blocking or asynchronously, as are all other actions that may need to wait for external events. There is a single event loop which uses a poll() or similar system call to wait for any pending I/O or other event to complete, and then dispatches the appropriate event handler(s). Such frameworks are often used instead of a multi-threaded model, eg. if threads are not available or to avoid complex inter-thread synchronisations and expensive context switch overhead.

Such frameworks are exactly where the non-blocking client library in MariaDB is useful. The Knowledgebase has all the details, but here is the basic idea:

To run a query, the application does a call like this:

mysql_real_query_start(&status, mysql, “SELECT * FROM t1”);

This will send data on the socket, and the server will start executing the query. But instead of waiting for the results, like in the normal  API, the call then returns immediately. The application can then check the status of the running query; in this case it finds that the query is waiting for data to arrive on such-and-such socket descriptor. The application will then register a callback and include the socket descriptor in the poll() call in its main loop. When data arrives, the callback fires and invokes:

mysql_real_query_cont(&status, mysql, <data_is_ready>)

Then the query processing continues, possibly returning multiple times while waiting for more data to arrive, and finally completing the operation.

The API is carefully designed to be just what is needed for event-driven frameworks like node.js to use it conveniently and efficiently. So I was really pleased to discover the mariasql project apply this theory to practise. I was of course especially pleased to see the benchmarks, where the non-blocking library is significantly faster than other MySQL bindings for node.js when queries (and thus waiting on the network) is involved. Without a proper non-blocking API, frameworks must resort to spawning background threads and defering blocking operations to such background threads; presumably the speedup comes from avoiding the inter-thread synchronisation and context switches. Of course avoiding the maintenance of background threading also simplifies the implementation.

Note by the way that the MariaDB non-blocking client library is fully compatible with all versions of the server, including all MySQL versions. So while mariasql must be linked against the MariaDB client library, it can be used with any MySQL server (the mariasql source tree seems to include the MariaDB client library to make this even easier for users).