views:

145

answers:

3

I'm in a situation where I need to make a call to a stored procedure from Rails. I can do it, but it either breaks the MySQL connection, or is a pseudo hack that requires weird changes to the stored procs. Plus the pseudo hack can't return large sets of data.

Right now my solution is to use system() and call the mysql command line directly. I'm thinking that a less sad solution would be to open my own MySQL connection independent of Active Record's connection.

I don't know of any reasons why this would be bad. But I also don't know the innards of the MySQL well enough to know it's 100% safe.

It would solve my problem neatly, in that with the controller actions that need to call a stored proc would open a fresh database connection, make the call and close it. I might sacrifice some performance, but if it works that's good enough. It also solves the issue of multiple users in the same process (we use mongrel, currently) in edge rails where it's now finally thread safe, as the hack requires two sql queries and I don't think I can guarantee I'm using the same database connection via Active Record.

So, is this a bad idea and/or dangerous?

+3  A: 

Ruby on Rails generally eschews stored procedures, or implementing any other business logic in the database. One might say that you're not following "the Rails way" to be calling a stored proc in the first place.

But if you must call the stored proc, IMO opening a second connection from Ruby must be preferable to shelling out with system(). The latter method would open a second connection to MySQL anyway, plus it would incur the overhead of forking a process to run the mysql client.

You should check out "Enterprise Recipes with Ruby and Rails" by Maik Schmidt. It has a chapter on calling stored procedures from Rails.

MySQL can handle more than one connection per request, though it will increase the load on the database server. You should open the second connection in a 'lazy' manner, only when you are sure you need it on a given request.

Anyway, if performance were important in this application, you wouldn't be using Rails! >:-)

(joking!)

Bill Karwin
Yeah, if I could avoid the stored proc I would. It can't be done given the time constraints we have (i.e., that code is already written).I just got Enterprise Recipes with Ruby and Rails" at the end of the last year, I'll definitely check it out.
Otto
Unfortunately the recipe in Enterprise Recipes with Ruby and Rails is talking to Oracle, which presumably doesn't have the same loss of state that the MySQL driver has.
Otto
+2  A: 

Considering how firmly RoR is intertwined with its own view of dbms usage, you probably should open a second connection to the database for any interaction it doesn't manage for you, just for SoC purposes if nothing else. It sounds from your description like it's the simplest approach as well, which is usually a strong positive sign.

Applications from other languages (esp. e.g. PHP) open multiple connections regularly (which doesn't make it desirable, but at least it demonstrates that mysql won't object.)

le dorfier
A: 

We've since tried the latest mysql gem from github and even that doesn't solve the problem.

We've patched the mysql adapter in Rails and that actually does work. All it does is make sure the MySQL connection has no more results before continuing on.

I'm not accepting this answer, yet, because I don't feel 100% that the fix is a good one. We haven't done quite enough testing. But I wanted to put it out there for anyone else looking at this question.

Otto
This ended up working reasonably well. The latest version of the mysql adapter from github (elia-mysql) is much more stable. Try that, if you have the same issues.
Otto