I am using MySQL for various personal projects and, because I have little experience with databases (except for very simple stuff), I recently decided to learn about stored procedures. The fact that all my queries were hardcoded made me feel uncomfortable.
Since then, I started getting errors randomly:
Lost connection to MySQL server during query
followed by
MySQL server has gone away.
I looked at
MySQL server has gone away in the documentation:
- [..] the server timed out and closed the connection. [..] By default, the server closes the connection after eight hours if nothing has happened.
Not the case. The error happened after a few seconds or minutes of connecting to the server.
- You (or the db administrator) has killed the running thread with a KILL statement or a mysqladmin kill command.
No, the server is still running. I can ping it, connect to it and issue commands without any problems. In fact, restarting my application works (only to fail again after a few queries).
- You tried to run a query after closing the connection to the server.
No.
- A client application running on a different host does not have the necessary privileges to connect to the MySQL server from that host.No, privileges didn't change while my program was running.
- You got a timeout from the TCP/IP connection on the client side.
Again, no. All suggestions about timeouts do not make sense. Actually, it looked like I was getting this error if I executed a bunch of stored procedure calls rapidly.
- Skipping more stuff about timeouts
- You can also get these errors if you send a query to the server that is incorrect or too large.This is getting interesting: a query [..] that is incorrect. Googling reveals posts such as this:
Right! Solved it...
[...]
There are 2 queries which make up a navigation panel on this chat system, one shows public chatrooms, the other private. The query which made up the private chatrooms was:
select distinct chatroom_label as label, chatroom_id as id
from chatroom where chatroom_date_deleted_timestamp is null
and chatroom_is_permanent_chatroom=1
order by chatroom_label desc, chatroom.chatroom_label asc
which is obviously wrong since it's ordering by the same column twice. This didn't produce an error but instead crashed the MySQL connection.
After double checking my queries, I found no problems. Indeed, very simple queries called in a loop would eventually fail.
Finally, after several hours of research, I stumbled upon
this thread and especially
this post:
Stored procedures always return one extra result set for the error
status of the procedure so you need to set the CLIENT_MULTI_RESULTS
option and need to iterate over the returned result sets using the
mysql_more_results() and mysql_next_result() API functions.
Looking back at my code, I have a stored procedure that looks like:
create procedure get_something(sid int)
begin
select * from somewhere where id=sid;
end
and I was calling it like this:
void f(MYSQL* handle)
{
mysql_query(handle, "select get_something(0)");
MYSQL_RES* r = mysql_store_result(handle);
MYSQL_ROW row;
for (;;)
{
row = mysql_fetch_row(r);
if (!row)
break;
use(row);
}
mysql_free_result(r);
}
The problem is that the query returned more than one result set. After leaking these result sets for a few times (random), the connection was dropped. There are two bugs here: mine (leaking result sets) and mysql's (shitty error messages).
The solution is to make sure all result sets are processed before issuing another query:
while(mysql_more_results(handle))
{
mysql_next_result(handle);
MYSQL_RES* r = mysql_store_result(handle);
if (res)
mysql_free_result(r);
}
In my case, since the actual call to mysql_query is wrapped inside another function, I added this bit
before doing any query. It solved the problem nicely.
For more informations and lots of "me too" posts,
google is always helpful.
No comments:
Post a Comment