2

I've done an awful lot of searching and troubleshooting to try and solve this myself.

My situation is that I've updated a host to Debian Squeeze (MySQL 5.1.49) from Debian Lenny (5.0-ish) and a previously working query that returned the expected result now returns an empty set.

So here goes on the background. In order to see if the data was problematic, I did a mysqldump of the database. I then copied that to my development machine (Mac OS X 10.6.8 with MySQL installed via Homebrew) and set up the database there. The query returned the results expected!

The code is based on an open source application, so I went back and did a clean install and database bootstrap on a Lenny host. I confirmed that the query returns what is expected.

I also did a fresh install of the application on a clean installed (not upgraded host) on Squeeze. The fresh install on Squeeze of the open source application works as expected.

I did a mysqldump from the fresh install of the application on Lenny. I then, on the clean Squeeze host, created a new database and loaded the Lenny dump into it. The query no longer returned the expected result. The same situation as the database upgraded through to Squeeze.

Here's a description of how things stand with the data.

First the tables:

mysql> describe roles;
+-------------------+-------------+------+-----+---------+----------------+
| Field             | Type        | Null | Key | Default | Extra          |
+-------------------+-------------+------+-----+---------+----------------+
| id                | int(11)     | NO   | PRI | NULL    | auto_increment |
| name              | varchar(40) | YES  |     | NULL    |                |
| authorizable_type | varchar(30) | YES  |     | NULL    |                |
| authorizable_id   | int(11)     | YES  |     | NULL    |                |
| created_at        | datetime    | YES  |     | NULL    |                |
| updated_at        | datetime    | YES  |     | NULL    |                |
+-------------------+-------------+------+-----+---------+----------------+

mysql> describe roles_users;
+------------+----------+------+-----+---------+-------+
| Field      | Type     | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+-------+
| user_id    | int(11)  | YES  | MUL | NULL    |       |
| role_id    | int(11)  | YES  | MUL | NULL    |       |
| created_at | datetime | YES  |     | NULL    |       |
| updated_at | datetime | YES  |     | NULL    |       |
+------------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)

You guessed it, these are from an authorization plugin circa Rails 2.1ish. Now in use by an application that has been upgraded to Rails 2.3.5 at this point.

I've verified that the descriptions for the tables are the same on both hosts.

Next the data:

mysql> select * from roles where id = 1;
+----+------------+-------------------+-----------------+---------------------+---------------------+
| id | name       | authorizable_type | authorizable_id | created_at          | updated_at          |
+----+------------+-------------------+-----------------+---------------------+---------------------+
|  1 | site_admin | Basket            |               1 | 2009-05-27 00:14:22 | 2009-05-27 00:14:22 |
+----+------------+-------------------+-----------------+---------------------+---------------------+
1 row in set (0.00 sec)

mysql> select * from roles_users where role_id = 1 and user_id = 1;
+---------+---------+---------------------+---------------------+
| user_id | role_id | created_at          | updated_at          |
+---------+---------+---------------------+---------------------+
|       1 |       1 | 2009-05-27 00:14:22 | 2009-05-27 00:14:22 |
+---------+---------+---------------------+---------------------+
1 row in set (0.00 sec)

Again, both hosts return the same result.

Here comes the query as expected to return (constructed by the authorization plugin to verify a user has the correct role on correct object in the system):

mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

And here it is again, on the Debian Squeeze host, returning the empty set:

mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
Empty set (0.00 sec)

Any ideas? Anyone else experience this?

Update for results requested from comment:

Here's without the LIMIT 1:

mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 ));
Empty set (0.00 sec)

Here's dropping the roles_users.user_id = 1 from the where clause:

mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles`.`id` = 1 ;
+----+
| id |
+----+
|  1 |
...
3 rows in set (0.00 sec)

Here's the above query, but showing the roles_users.user_id in the select:

mysql> SELECT `roles`.id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles`.`id` = 1 ;
+----+---------+
| id | user_id |
+----+---------+
|  1 |       1 |
...
3 rows in set (0.00 sec

and finally here's dropping the roles.id from where clause, but keeping the roles_users.user_id:

mysql> SELECT `roles`.id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE `roles_users`.user_id = 1;                                                                             
+----+---------+
| id | user_id |
+----+---------+
...
|  1 |       1 |
...
9 rows...
2
  • So the matching data is definitely there. I would like to avoid reformulating the query and find the problem (configuration? environmental variable? bug?) that is preventing it from working in MySQL.
    – mcginniwa
    Aug 19, 2011 at 0:41
  • Thanks for the tip about updating the question.
    – mcginniwa
    Aug 19, 2011 at 3:01

2 Answers 2

0

I've found the root cause that makes this issue happen on Debian Squeeze MySQL 5.1.49; the query will return an empty set when the roles_users table has more than one distinct user_id for a role_id.

I.e. if I have this:

mysql> SELECT `roles_users`.role_id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id order by role_id;
+---------+---------+
| role_id | user_id |
+---------+---------+
|       1 |       1 |
|       2 |       1 |
|       3 |       1 |
|       4 |       1 |
|       5 |       1 |
|       6 |       2 |
+---------+---------+
6 rows in set (0.01 sec)

I get what I expect for this:

mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1) AND  ((`roles_users`.user_id = 1)) LIMIT 1;
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

but when I have this (an addition user_id that has role_id 1):

mysql> SELECT `roles_users`.role_id, `roles_users`.user_id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id order by role_id;
+---------+---------+
| role_id | user_id |
+---------+---------+
|       1 |       1 |
|       1 |       5 |
|       2 |       1 |
|       3 |       1 |
|       4 |       1 |
|       4 |       5 |
|       5 |       1 |
|       6 |       2 |
+---------+---------+
8 rows in set (0.00 sec)

I get this:

mysql> SELECT `roles`.id FROM `roles` INNER JOIN `roles_users` ON `roles`.id = `roles_users`.role_id WHERE (`roles`.`id` = 1 ) AND ((`roles_users`.user_id = 1 )) LIMIT 1 ;
Empty set (0.00 sec)

So there are two possibilities.

Either the query, that works with that data set (more than one user_id with the same role_id) was always invalid and MySQL 5.0.51a-24+lenny4 worked with it anyway even though it shouldn't have OR there is a bug in MySQL 5.1.49-3 (Debian).

I'm going to report on the forum for bugs at MySQl and see what response I get.

1
  • Just to clarify. This isn't a bug that is caused by upgrading from Lenny to Squeeze per se. It appears to be a bug in Squeeze's version of MySQL and my previous "working on Squeeze " data just didn't trigger it.
    – mcginniwa
    Aug 23, 2011 at 5:09
0

To fix the problem upgrade to 5.1.58-1~dotdeb.1 on Squeeze. I used dotdeb because there wasn't a Squeeze backports later version of MySQL.

Here are my basic steps (as root):

  • cp /etc/mysql/my.cnf to temp location NECESSARY ONLY IF you have custom configuration

  • aptitude purge libmysqlclient-dev libmysqlclient16 mysql-client mysql-client-5.1 mysql-common mysql-server mysql-server-5.1 mysql-server-core-5.1

  • set up /etc/apt/sources.list.d/dotdeb.list as per http://www.dotdeb.org/instructions/

  • aptitude update
  • wget http://www.dotdeb.org/dotdeb.gpg
  • cat dotdeb.gpg | apt-key add -
  • aptitude update
  • be prepared with your previous mysql root user's password
  • aptitude install libmysqlclient libmysqlclient-dev mysql-server mysql-common mysql-client libmysql-ruby1.8 mytop apache2-threaded-dev

NECESSARY ONLY IF you have custom configuration as mentioned above:

  • /etc/init.d/mysql stop
  • cp old my.cnf (if it was already updated to squeeze) to /etc/mysql/my.cnf
  • /etc/init.d/mysql start

That made my query return the expected id rather than an empty set.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.