查询返回空集Mysql 5.1.49但返回5.0-ish上的内容

时间:2011-08-18 05:28:41

标签: mysql sql mysqldump

我已经做了大量的搜索和故障排除,试图自己解决这个问题。

我的情况是我已经从Debian Lenny(5.0-ish)更新了Debian Squeeze(MySQL 5.1.49)的主机,并且返回预期结果的先前工作查询现在返回一个空集。

所以这里是背景。为了查看数据是否有问题,我做了一个数据库的mysqldump。然后我将其复制到我的开发机器(通过Homebrew安装MySQL的Mac OS X 10.6.8)并在那里设置数据库。查询返回了预期的结果!

代码基于一个开源应用程序,所以我回去并在Lenny主机上做了一个干净的安装和数据库引导程序。我确认查询返回了预期的内容。

我还在Squeeze上的干净安装(未升级的主机)上重新安装了该应用程序。开源应用程序的Squeeze上的全新安装按预期工作。

我在Lenny的应用程序的全新安装上做了一个mysqldump。然后,我在干净的Squeeze主机上创建了一个新数据库,并将Lenny转储加载到其中。查询不再返回预期结果。与数据库升级到Squeeze的情况相同。

以下是对数据的处理方式的描述。

首先是表格:

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)

你猜对了,这些是来自Rails 2.1ish的授权插件。现在由一个已经升级到Rails 2.3.5的应用程序使用。

我已经确认两台主机上的表格描述相同。

接下来的数据:

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)

同样,两个主机都返回相同的结果。

以下是要返回的查询(由授权插件构造以验证用户在系统中的正确对象上具有正确的角色):

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)

再次,在Debian Squeeze主机上,返回空集:

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)

有什么想法吗?还有其他人经历过这个吗?

对于评论请求的结果

更新

这里没有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)

这里从where子句中删除roles_users.user_id = 1:

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)

以上是上述查询,但在select:

中显示了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`.`id` = 1 ;
+----+---------+
| id | user_id |
+----+---------+
|  1 |       1 |
...
3 rows in set (0.00 sec

最后这里从where子句中删除roles.id,但保留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 个答案:

答案 0 :(得分:0)

我找到了导致这个问题发生在Debian Squeeze MySQL 5.1.49上的根本原因;当roles_users表具有多个role_id的不同user_id时,查询将返回一个空集。

即。如果我有这个:

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)

我得到了我对此的期望:

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)

但是当我有这个(添加了具有role_id 1的user_id)时:

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)

我明白了:

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)

所以有两种可能性。

使用该数据集的查询(多个具有相同role_id的user_id)始终无效,并且MySQL 5.0.51a-24 + lenny4无论如何都使用它,即使它不应该有OR有一个MySQL 5.1.49-3(Debian)中的错误。

我将在论坛上报告MySQl上的错误,看看我得到了什么回应。

答案 1 :(得分:0)

要解决问题,请在Squeeze上升级到5.1.58-1~dotdeb.1。我使用了dotdeb,因为没有Squeeze后向版本的MySQL。

以下是我的基本步骤(以root身份):

  • cp /etc/mysql/my.cnf至临时位置仅在您有自定义配置时必须

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

  • 根据http://www.dotdeb.org/instructions/设置/etc/apt/sources.list.d/dotdeb.list

  • aptitude update
  • wget http://www.dotdeb.org/dotdeb.gpg
  • cat dotdeb.gpg | apt-key add -
  • aptitude update
  • 准备好您以前的mysql root用户密码
  • aptitude install libmysqlclient libmysqlclient-dev mysql-server mysql-common mysql-client libmysql-ruby1.8 mytop apache2-threaded-dev

如果你有如上所述的自定义配置,则必须:

  • /etc/init.d/mysql stop
  • cp old my.cnf(如果它已经更新为挤压)到/etc/mysql/my.cnf
  • /etc/init.d/mysql start

这使我的查询返回预期的id而不是空集。