NeverBlock and Non-Blocking Database Adapters
NeverBlock is a library that, using Ruby 1.9 fibers, allows to write non-blocking code. The first database to profit from NeverBlock was Postgres (read the InfoQ article about Fibers and NeverBlock). And now, just a few days later, NeverBlock added support for MySQL as well, using the new MySQLPlus driver. MySQLPlus builds on top of the original Ruby MySQL driver but adds asynchronous query processing support and threaded access support.
There's also another project aiming to bring asynchronous operations to Ruby's MySQL connection called Asymy. InfoQ talked to Roger Pack who worked on MySQLPlus; we were particularly interested in the differences between MySQLPlus and Asymy, and why they created a new adapter.
First some history: the former state of the art was the C MySQL lib, which blocked for any queries. Both try to overcome that.
MySQLPlus is basically a fork of the standard MySQL Ruby C lib which adds some multi-thread friendly aspects, specifically the ability to not block on IO until a query returns.
Asymy is a pure Ruby asynchronous MySQL adapter. It's written in Ruby, so parses things much more slowly (about 10x slower), and is also fairly new so still has a few bugs lurking.
I'd say a difference between them is that Asymy is "only" for Event driven while MySQLPlus works with threads and event driven. Its event driven aspect is a little limited since you can't actually detect when to wait on IO while a query is being read in, so it's not perfect yet, but it's a step in the right direction.
In reality what occurred is that we started with Asymy, then Muhammed [Ali, one of the persons behind NeverBlock] found out that the standard C MySql libs, with slight modification, yield themselves almost equally as well to multi-threading, so we switched to those. The MySQLPlus library is a small change to Tomita Masahiro's library.
So I guess there is some duplication between them, it's mostly a question of C versus Ruby, and we didn't write the C, so no duplication there.
So NeverBlock now works with MySQLPlus, will it also work with plain Event Machine?
NeverBlock is basically the combination of Fibers, EventMachine and Postgres or MySQLPlus drivers. So the answer is yes, if you apply some small patches to it, so if you enjoy the EventMachine style of staged programming it would work with 1.8.x even.
Note that MySQLPlus already works as a thread friendlier drop in replacement for the 1.8.x MySQL drivers. It also happens to work with NeverBlock and 1.9, which is its original goal.
What are the future plans for the project? Do you have any intentions to adapt other databases too?
Muhammed mentioned the potential. I don't have any since I think we've covered the bases pretty well.
Future plans are to work to get rails 2.2 working with NeverBlock and MySQLPlus, hopefully with good performance results.
MySQLPlus is also used in a completely asynchronous Event Machine MySQL client developed by Aman Gupta, one of the co-authors of MySQLPlus.
Of course, Postgres and MySQL aren't the only databases used with Ruby, so we talked to KUBO Takehiro, an author of ruby-oci8, the interface to Oracle databases. We asked him about his opinion of NeverBlock and if it would be easy to integrate it with ruby-oci8:
In my opinion it isn't easy. Neverblock-pg uses
PGconn#send_queryto issue a query then suspends the fiber until the query is finished. But ruby-oci8's non blocking mode is different. When a query is executed, ruby-oci8 in a non blocking mode waits the result but doesn't block other threads. There is no place outside ruby-oci8 to add code to suspend the fiber. But I have no intention of modifying ruby-oci8 to adapt NeverBlock. That's because users can use non-blocking operations transparently without using NeverBlock fiber pool.
In addition I'm not sure whether NeverBlock is must for non blocking operations. If ruby-pg wraps blocking operations by
rb_thread_blocking_region()(new in ruby 1.9), it doesn't block other threads (see The Futures of Ruby Threading).
In spite of what I mentioned above, I appreciate its effort for adding connection pooling feature to activerecord adapters. It is exactly what I want.
We also asked Jamis Buckis, who is responsible for the sqlite3-ruby adapter, if it would make sense to implement an asynchronous interface to SQLite:
Honestly, not really. SQLite is an embedded database, not a client/ server model like MySQL or PostgreSQL. In order to support async queries to SQLite, you'd first need to convert it into a server, so that it runs in a separate process from your application, and by the time you've done that...there really is no more reason to be using sqlite.What do you think? Is non-blocking database access necessary for better performance?
Really, I strongly discourage people from using SQLite in a production web environment. It is fantastic for testing and development, and works great for embedded apps, but in a web environment it just doesn't work nearly as well as the client/server models.
using mysqlplus with rails 2.2